it-swarm-vi.com

Làm thế nào để chỉ in cột cuối cùng?

echo -e 'one two three\nfour five six\nseven eight nine'
one two three
four five six
seven eight nine

làm thế nào tôi có thể làm một số "MAGIC" để có được đầu ra này?:

three
six
nine

CẬP NHẬT: Tôi không cần nó theo cách cụ thể này, tôi cần một giải pháp chung để cho dù có bao nhiêu cột trong một hàng, ví dụ: awk luôn hiển thị cột cuối cùng.

27
LanceBaynes

Nó thậm chí có thể được thực hiện chỉ với 'bash', không có 'sed', 'awk' hoặc là '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
6
jfg956

Thử:

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

Nó dễ hơn bạn nghĩ.

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

Hãy thử grep (ngắn hơn/đơn giản hơn, nhưng chậm hơn 3 lần so với awk vì sử dụng regex):

grep -o '\S\+$' <(echo -e '... seven eight nine')

Hoặc ex (thậm chí chậm hơn, nhưng nó in toàn bộ bộ đệm sau khi hoàn tất, hữu ích hơn khi cần sắp xếp hoặc chỉnh sửa tại chỗ):

ex -s +'%s/^.*\s//g' -c'%p|q!' <(echo -e '... seven eight nine')
ex +'%norm $Bd0' -sc'%p|q!' infile

Để thay đổi tại chỗ, thay thế -sc'%p|q!' với -scwq.

Hoặc bash:

while read line; do arr=($line); echo ${arr[-1]}; done < someinput

Hiệu suất

Cho tệp 1GB được tạo thông qua:

$ hexdump -C /dev/urandom | rev | head -c1G | pv > datafile

Tôi đã thực hiện thống kê thời gian phân tích cú pháp (chạy ~ 3x và ở mức thấp nhất, được thử nghiệm trên MBP OS X):

  • sử dụng awk:

    $ time awk '{print $NF}' datafile > /dev/null
    real    0m12.124s
    user    0m10.704s
    sys 0m0.709s
    
  • sử dụng 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
    
  • sử dụng Perl:

    $ time Perl -lane 'print $F[-1]' datafile > /dev/null
    real    0m48.292s
    user    0m47.601s
    sys 0m0.396s
    
  • sử dụng 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
    
  • sử dụng 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
    
  • sử dụng bash:

    $ time while read line; do arr=($line); echo ${arr[-1]}; done < datafile > /dev/null
    real    9m42.807s
    user    8m12.553s
    sys 1m1.955s
    
12
kenorb
... | Perl -lane 'print $F[-1]'
6
glenn jackman

Nó cũng có thể được thực hiện bằng cách sử dụng 'sed':

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

Cập nhật :

hoặc đơn giản hơn:

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

Hoặc sử dụng cut :

echo -e 'one two three\nfour five six\nseven eight nine' | cut -f 3 -d' '

mặc dù điều này không thỏa mãn yêu cầu 'giải pháp chung'. Sử dụng rev hai lần chúng ta cũng có thể giải quyết điều này:

echo -e 'one two three\nfour five six\nseven eight nine' | rev | cut -f 1 -d' ' | rev
5
Tim

Sử dụng awk trước tiên bạn có thể kiểm tra xem có ít nhất một cột không.

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

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

Trong Perl, điều này có thể được thực hiện như sau:

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

đầu ra:

$ Perl last.pl
5
$

Bạn cũng có thể lặp qua một tệp, đây là một đoạn mã ví dụ mà tôi đã viết để phân tích một tệp có tên là bank.dat

dữ liệu ví dụ trong ngân sách.dat:

Rent              500
Food              250
Car               300
Tax               100
Car Tax           120
Mag Subscription  15

(bạn có thể thấy tôi chỉ cần chụp cột "cuối cùng", không phải cột 2)

Kịch bản:

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