Como imprimir apenas a última coluna?

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

como posso fazer um "MAGIC" obter essa saída?:

three
six
nine

ATUALIZAÇÃO: Eu não preciso disso desta maneira específica, eu preciso de uma solução geral para que não importa quantas colunas estão em uma linha, por exemplo: o awk sempre exibe a última coluna.

    
por LanceBaynes 20.07.2011 / 19:23

9 respostas

5

Pode até ser feito apenas com 'bash' , sem 'sed' , 'awk' ou '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
    
por 20.07.2011 / 20:14
48

Tente:

echo -e 'one two three\nfour five six\nseven eight nine' | awk '{print $NF}'
    
por 20.07.2011 / 19:26
12

É mais fácil do que você pensa.

$ echo one two three | awk '{print $NF}'
three
    
por 21.07.2011 / 00:38
8

Teste grep (mais curto / mais simples, mas 3x mais lento que awk devido ao uso de regex):

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

Ou ex (ainda mais lento, mas imprime todo o buffer após o término, mais útil quando precisa ser classificado ou editado no local):

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

Para alterar no local, substitua -sc'%p|q!' por -scwq .

Ou bash :

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

Desempenho

Dado o arquivo gerado de 1 GB via:

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

Eu executei as estatísticas de tempo de análise (correu ~ 3x e levou o menor, testado no MBP OS X):

  • usando awk :

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

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

    $ time while read line; do arr=($line); echo ${arr[-1]}; done < datafile > /dev/null
    real    9m42.807s
    user    8m12.553s
    sys 1m1.955s
    
por 16.10.2015 / 01:47
6
... | perl -lane 'print $F[-1]'
    
por 20.07.2011 / 19:49
5

Isso também pode ser feito usando 'sed' :

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

Atualização:

ou mais simplesmente:

echo -e 'one two three\nfour five six\nseven eight nine' | sed -e 's/^.* //'
    
por 20.07.2011 / 19:46
4

Ou usando cut :

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

embora isso não satisfaça o requisito de 'solução geral'. Usando rev duas vezes podemos resolver isso também:

echo -e 'one two three\nfour five six\nseven eight nine' | rev | cut -f 1 -d' ' | rev
    
por 21.07.2011 / 00:38
2

Usando awk , você pode primeiro verificar se há pelo menos uma coluna.

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

echo 1 2 3 | awk '{if (NF >= 1) print $NF}'
    
por 18.03.2013 / 10:11
1

No perl isso pode ser feito da seguinte forma:

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

saída:

$ perl last.pl
5
$

Você também pode percorrer um arquivo, aqui está um script de exemplo que escrevi para analisar um arquivo chamado budget.dat

dados de exemplo em budget.dat:

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

(você pode ver que eu precisava capturar apenas a "última" coluna, não apenas a coluna 2)

O script:

#!/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";
    
por 29.04.2015 / 17:54