it-swarm-tr.com

Yalnızca son sütunu nasıl yazdırabilirim?

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

nasıl bu "MAGIC" bu çıktıyı alabilirim ?:

three
six
nine

GÜNCELLEME: Bu belirli bir şekilde ihtiyacım yok, genel bir çözüme ihtiyacım var, böylece üst üste kaç sütun olursa olsun, örneğin: awk her zaman son sütunu görüntüler.

27
LanceBaynes

Hatta 'bash', 'sed' Veya 'awk' Olmadan yalnızca 'Perl' İle yapılabilir:

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

Deneyin:

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

Düşündüğünden daha kolay.

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

grep (daha kısa/basit, ancak normal ifade kullanımı nedeniyle awk 'den 3 kat daha yavaş) deneyin:

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

Veya ex (daha da yavaş, ancak bittikten sonra tüm arabelleği yazdırır, yerinde sıralanması veya düzenlenmesi gerektiğinde daha kullanışlıdır):

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

Yerinde değiştirmek için -sc'%p|q!' ile -scwq.

Veya bash:

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

Verim

Oluşturulan 1GB dosyası şu şekilde verilir:

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

Ayrıştırma süresi istatistiklerini gerçekleştirdim (~ 3x koştum ve en düşük değeri aldım, MBP OS X'te test edildi):

  • awk kullanarak:

    $ time awk '{print $NF}' datafile > /dev/null
    real    0m12.124s
    user    0m10.704s
    sys 0m0.709s
    
  • grep kullanarak:

    $ 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 kullanarak:

    $ time Perl -lane 'print $F[-1]' datafile > /dev/null
    real    0m48.292s
    user    0m47.601s
    sys 0m0.396s
    
  • rev + cut kullanarak:

    $ 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 kullanarak:

    $ 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 kullanarak:

    $ 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

Ayrıca 'sed':

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

Güncelleme:

veya daha basit:

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

Veya cut kullanarak:

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

ancak bu 'genel çözüm' gereksinimini karşılamamaktadır. rev iki kez kullanarak bunu da çözebiliriz:

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

awk kullanarak önce en az bir sütun olup olmadığını kontrol edebilirsiniz.

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

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

Perl'de bu şu şekilde yapılabilir:

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

çıktı:

$ Perl last.pl
5
$

Ayrıca bir dosya üzerinden döngü olabilir, heres budget.dat adlı bir dosyayı ayrıştırmak için yazdığım örnek bir komut dosyası

budget.dat içindeki örnek veriler:

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

(yalnızca 2. sütunu değil, yalnızca "son" sütunu yakalamak için gerekli olduğunu görebilirsiniz)

Senaryo:

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