마지막 열만 인쇄하는 방법?


25
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는 항상 마지막 열을 표시합니다.


2
랜스는 질문하기 전에 질문을 조사하십시오. 게시물 제목 줄을 Google에서 검색하면 스 니펫에 답변이 표시됩니다. "awk last column"을 검색하면 결과 1로 시작하는 몇 가지 훌륭한 답변이 제공됩니다. 또한 이 5 분짜리 awk 입문서 는 모든 것을 읽을 가치가 있으므로 앞으로 무엇이 가능한지 알 수 있습니다.
Caleb

답변:


6

그것도 단지와 함께 할 수 '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
glenn jackman

@ glenn : 이것이 첫 번째 아이디어 였지만 '읽기'설명서를 읽을 때 유용한 배열 함수를 보았습니다. 또한 오른쪽에서 색인 된 필드를 제공하도록 쉽게 수정할 수 있습니다.
jfg956

2
bash배열 인덱스는 산술 평가 대상이므로 echo ${line[nb - 1]}충분합니다. 에 대해 말하면 bash“nb”항목을 건너 뛸 수 있습니다 echo ${line[-1]}.. 나중에 더 이식 가능한 대안 :echo ${line[@]: -1]} . ( 다른 곳 에서 부정적인 지수에 대한 Stephane Chazelas의 의견을 보십시오 .)
manatwork

53

시험:

echo -e 'one two three\nfour five six\nseven eight nine' | awk '{print $NF}'


awk는 99 개의 필드로 제한된다는 점에 유의하십시오 ... : / 이것은 지난 날에 물린 것입니다 ps -ef | awk '{ print $NF }'. ( gnu.org/software/autoconf/manual/autoconf-2.67/html_node/… : "전통적인 Awk는 레코드에서 99 개의 필드로 제한됩니다. Tru64와 같은 일부 Awk 구현은 참조하지 않아도 입력을 분할합니다 이 문제를 피하려면 'FS'를 특이한 문자로 설정하고 split을 사용하십시오. ")
Olivier Dulac

@OlivierDulac 어떤 awk구현에 그 한계가 있습니까? 나는 그것을 본 적이 없다. 내가 mawk에 질식 것입니다 32768하지만 내 gawkigawk행복하게 수백만을 처리 할 수 있습니다. 비지 박스조차도 awk수백만을 처리 할 수 ​​있습니다. 나는 awk100 개의 필드를 처리 할 수없는 것을 결코 보지 못했습니다 . 결국 소수입니다. 정보가 여전히 관련성이 있습니까? 솔라리스에서도?
terdon

@ terdon, 내 의견에 링크를 참조하십시오 ^^ (그리고 일부 "레거시"시스템은 일부 환경에서 loooooooog 시간을 살아남을 수 있다고 생각합니다. 내장 (예 : $ BASH_SOURCE), NF> 99에서의 awk choke 등 ... :()
Olivier Dulac

@OlivierDulac 공정합니다. 난 그냥 건너 오지 않았습니다. 99가 작은 숫자이기 때문에 오늘날 거의 사라지지 않기를 바랍니다.
terdon

14

생각보다 쉽습니다.

$ echo one two three | awk '{print $NF}'
three

11

시도하십시오 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

6
... | perl -lane 'print $F[-1]'

요점 : -a, 자동 분할 필드를 @F배열로; -l잘라 내고 $/(입력 레코드 구분 기호) 저장합니다 $\(출력 레코드 구분 기호). 으로 제공된 8 진수가 없기 때문에 -l, 원본 $/은 인쇄 (줄 끝)에 적용됩니다. -n루프 코드; -e바로 다음에 코드를 실행하십시오. 참조하십시오 man perlrun.
Jonathan Komar

5

다음을 사용하여 수행 할 수도 있습니다 'sed'.

echo -e 'one two three\nfour five six\nseven eight nine' | sed -e 's/^.* \([^ ]*\)$/\1/'

최신 정보:

또는 더 간단하게 :

echo -e 'one two three\nfour five six\nseven eight nine' | sed -e 's/^.* //'

더 간단하게 더 좋습니다!
mdpc

@ mdpc : 동의하지만 더 복잡한 솔루션이 이미 게시되었으므로 계속하기로 결정했습니다.
jfg956

5

또는 사용 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'가 모든 유닉스 (AIX, Solaris 등)에서 발견되거나 모든 Linux에 설치되어 있지만 훌륭한 대안 솔루션이라고 생각하지 않습니다.
jfg956

1
double rev의 경우 +1이지만 보조 메모 rev로 '넓은'문자, 단일 바이트 문자는 작동하지 않습니다.
Marcin

2

사용하여 awk하나 이상의 열이있는 경우 먼저 확인 할 수 있습니다합니다.

echo | awk '{if (NF >= 1) print $NF}'

echo 1 2 3 | awk '{if (NF >= 1) print $NF}'

3
또는 덜 장황하게 awk 'NF{print $NF}'.
manatwork

1

펄에서는 다음과 같이 할 수 있습니다 :

#!/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";

나는 다른 누군가가 이미 똑같이 논평했다는 것을 깨달았습니다. 죄송합니다. 적어도 몇 가지 예가 있기를 바랍니다. 어쨌든 토론에 추가되기를 바랍니다.
urbansumo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.