it-swarm.com.de

Wie drucke ich nur die letzte Spalte?

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

wie kann ich etwas "MAGIC" machen, um diese Ausgabe zu bekommen?:

three
six
nine

UPDATE: Ich brauche es nicht auf diese spezielle Weise, ich brauche eine allgemeine Lösung, damit unabhängig von der Anzahl der Spalten in einer Zeile, z. B.: Awk immer die letzte Spalte anzeigt.

27
LanceBaynes

Es kann sogar nur mit 'bash', Ohne 'sed', 'awk' Oder 'Perl' Durchgeführt werden:

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

Versuchen:

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

Es ist einfacher als du denkst.

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

Versuchen Sie grep (kürzer/einfacher, aber 3x langsamer als awk aufgrund der Verwendung von Regex):

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

Oder ex (noch langsamer, aber es druckt den gesamten Puffer nach dem Abschluss aus, was nützlicher ist, wenn er direkt sortiert oder bearbeitet werden muss):

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

Ersetzen Sie -sc'%p|q!' mit -scwq.

Oder bash:

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

Performance

Angesichts der generierten 1-GB-Datei über:

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

Ich habe die Parsing-Zeitstatistik durchgeführt (lief ~ 3x und nahm die niedrigste, getestet unter MBP OS X):

  • using awk:

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

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

Dies kann auch mit 'sed' Durchgeführt werden:

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

pdate :

oder einfacher:

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

Oder mit cut :

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

obwohl dies nicht die Anforderung der "allgemeinen Lösung" erfüllt. Mit rev zweimal können wir dies auch lösen:

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

Mit awk können Sie zunächst prüfen, ob mindestens eine Spalte vorhanden ist.

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

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

In Perl kann dies wie folgt erfolgen:

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

ausgabe:

$ Perl last.pl
5
$

Sie können auch eine Datei durchlaufen. Hier ist ein Beispielskript, das ich geschrieben habe, um eine Datei namens budget.dat zu analysieren

beispieldaten in budget.dat:

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

(Sie können sehen, dass ich nur die "letzte" Spalte erfassen musste, nicht nur Spalte 2)

Das Skript:

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