echo -e 'one two three\nfour five six\nseven eight nine'
one two three
four five six
seven eight nine
어떻게 "MAGIC"이이 출력을 얻을 수 있습니까? :
three
six
nine
업데이트 :이 특정 방식으로 필요하지 않습니다. 행에 몇 개의 열이 있든 관계없이 일반적인 솔루션이 필요합니다. 예 : awk는 항상 마지막 열을 표시합니다.
echo -e 'one two three\nfour five six\nseven eight nine'
one two three
four five six
seven eight nine
어떻게 "MAGIC"이이 출력을 얻을 수 있습니까? :
three
six
nine
업데이트 :이 특정 방식으로 필요하지 않습니다. 행에 몇 개의 열이 있든 관계없이 일반적인 솔루션이 필요합니다. 예 : awk는 항상 마지막 열을 표시합니다.
답변:
그것도 단지와 함께 할 수 'bash'
없는 'sed'
, 'awk'
또는 'perl'
:
echo -e 'one two three\nfour five six\nseven eight nine' |
while IFS=" " read -r -a line; do
nb=${#line[@]}
echo ${line[$((nb - 1))]}
done
... | while read -r line; do echo ${line##* }; done
bash
배열 인덱스는 산술 평가 대상이므로 echo ${line[nb - 1]}
충분합니다. 에 대해 말하면 bash
“nb”항목을 건너 뛸 수 있습니다 echo ${line[-1]}
.. 나중에 더 이식 가능한 대안 :echo ${line[@]: -1]}
. ( 다른 곳 에서 부정적인 지수에 대한 Stephane Chazelas의 의견을 보십시오 .)
시험:
echo -e 'one two three\nfour five six\nseven eight nine' | awk '{print $NF}'
ps -ef | awk '{ print $NF }'
. ( gnu.org/software/autoconf/manual/autoconf-2.67/html_node/… : "전통적인 Awk는 레코드에서 99 개의 필드로 제한됩니다. Tru64와 같은 일부 Awk 구현은 참조하지 않아도 입력을 분할합니다 이 문제를 피하려면 'FS'를 특이한 문자로 설정하고 split을 사용하십시오. ")
awk
구현에 그 한계가 있습니까? 나는 그것을 본 적이 없다. 내가 mawk
에 질식 것입니다 32768
하지만 내 gawk
와 igawk
행복하게 수백만을 처리 할 수 있습니다. 비지 박스조차도 awk
수백만을 처리 할 수 있습니다. 나는 awk
100 개의 필드를 처리 할 수없는 것을 결코 보지 못했습니다 . 결국 소수입니다. 정보가 여전히 관련성이 있습니까? 솔라리스에서도?
시도하십시오 grep
(짧거나 간단하지만 awk
정규식 사용으로 인해 3 배 느립니다 ).
grep -o '\S\+$' <(echo -e '... seven eight nine')
또는 ex
(더 느리지 만 완료 후 전체 버퍼를 인쇄하므로 정렬하거나 편집해야 할 때 더 유용합니다).
ex -s +'%s/^.*\s//g' -c'%p|q!' <(echo -e '... seven eight nine')
ex +'%norm $Bd0' -sc'%p|q!' infile
대신에 장소 변경하기 -sc'%p|q!'
로-scwq
.
또는 bash
:
while read line; do arr=($line); echo ${arr[-1]}; done < someinput
다음을 통해 생성 된 1GB 파일을 가정하십시오.
$ hexdump -C /dev/urandom | rev | head -c1G | pv > datafile
파싱 시간 통계를 수행했습니다 (MBP OS X에서 테스트 ~ ~ 3 배, 가장 낮음).
사용하여 awk
:
$ time awk '{print $NF}' datafile > /dev/null
real 0m12.124s
user 0m10.704s
sys 0m0.709s
사용하여 grep
:
$ time grep -o '\S\+$' datafile > /dev/null
real 0m36.731s
user 0m36.244s
sys 0m0.401s
$ time grep -o '\S*$' datafile > /dev/null
real 0m40.865s
user 0m39.756s
sys 0m0.415s
사용하여 perl
:
$ time perl -lane 'print $F[-1]' datafile > /dev/null
real 0m48.292s
user 0m47.601s
sys 0m0.396s
rev
+ 사용 cut
:
$ time (rev|cut -d' ' -f1|rev) < datafile > /dev/null
$ time rev datafile | cut -d' ' -f1 | rev > /dev/null
real 1m10.342s
user 1m19.940s
sys 0m1.263s
사용하여 ex
:
$ time ex +'%norm $Bd0_' -sc'%p|q!' datafile > /dev/null
real 3m47.332s
user 3m42.037s
sys 0m2.617s
$ time ex +'%norm $Bd0' -sc'%p|q!' datafile > /dev/null
real 4m1.527s
user 3m44.219s
sys 0m6.164s
$ time ex +'%s/^.*\s//g' -sc'%p|q!' datafile > /dev/null
real 4m16.717s
user 4m5.334s
sys 0m5.076s
사용하여 bash
:
$ time while read line; do arr=($line); echo ${arr[-1]}; done < datafile > /dev/null
real 9m42.807s
user 8m12.553s
sys 1m1.955s
... | perl -lane 'print $F[-1]'
-a
, 자동 분할 필드를 @F
배열로; -l
잘라 내고 $/
(입력 레코드 구분 기호) 저장합니다 $\
(출력 레코드 구분 기호). 으로 제공된 8 진수가 없기 때문에 -l
, 원본 $/
은 인쇄 (줄 끝)에 적용됩니다. -n
루프 코드; -e
바로 다음에 코드를 실행하십시오. 참조하십시오 man perlrun
.
또는 사용 cut
:
echo -e 'one two three\nfour five six\nseven eight nine' | cut -f 3 -d' '
'일반 솔루션'요구 사항을 충족하지는 않지만 rev
두 번 사용하면 이 문제도 해결할 수 있습니다.
echo -e 'one two three\nfour five six\nseven eight nine' | rev | cut -f 1 -d' ' | rev
rev
로 '넓은'문자, 단일 바이트 문자는 작동하지 않습니다.
펄에서는 다음과 같이 할 수 있습니다 :
#!/usr/bin/perl
#create a line of arbitrary data
$line = "1 2 3 4 5";
# splt the line into an array (we call the array 'array', for lolz)
@array = split(' ', $line);
# print the last element in the array, followed by a newline character;
print "$array[-1]\n";
산출:
$ perl last.pl
5
$
budget.dat라는 파일을 구문 분석하기 위해 작성한 예제 스크립트를 통해 파일을 반복 할 수도 있습니다.
budget.dat의 데이터 예 :
Rent 500
Food 250
Car 300
Tax 100
Car Tax 120
Mag Subscription 15
(열 2가 아닌 "마지막"열만 캡처해야 함을 알 수 있습니다)
스크립트 :
#!/usr/bin/perl
$budgetfile = "budget.dat";
open($bf, $budgetfile)
or die "Could not open filename: $filename $!";
print "-" x 50, "\n";
while ( $row = <$bf> ) {
chomp $row;
@r = split (' ', $row);
print "$row ";
$subtotal += $r[-1];
print "\t$subtotal\n";
}
print "-" x 50, "\n";
print "\t\t\t Total:\t$subtotal\n\n";