Como imprimir as duas últimas colunas usando awk


106

Tudo que eu quero são as duas últimas colunas impressas.


6
Não tenho certeza de por que isso tem 87 votos positivos, certamente pode ser melhorado com um exemplo, no mínimo.
Arj

Provavelmente porque a pergunta é extremamente simples por natureza e facilmente compreendida sem um exemplo, o que é raro, mas neste caso parece funcionar. O problema aqui não é falta de informação eu acho, mas mais que mostra falta de pesquisas independentes.
DryLabRebel

Esta pergunta também é uma duplicata desta pergunta.
DryLabRebel

Respostas:


194

Você pode usar a variável NFque é definida como o número total de campos no registro de entrada:

awk '{print $(NF-1),"\t",$NF}' file

isso pressupõe que você tenha pelo menos 2 campos.


1
Você precisa de uma vírgula - já que estamos sendo exigentes hoje: o espaço concatena os campos, a vírgula separa os campos em uma instrução de impressão. Isso unirá os dois campos
Jim Mcnamara

18
Agora você está imprimindo "campo-OFS-guia-campo-OFS". Deve ser awk '{print $(NF-1) "\t" $NF}' fileou awk '{print $(NF-1), $NF}' fileou awk 'BEGIN{OFS="\t"} {print $(NF-1), $NF}' file.
Pausado até novo aviso.

Apenas para adicionar ao comentário anterior, o problema de usar '{print $x,"\t",$y}'é que awk interpreta cada variável separada por vírgula como seu próprio campo, então o resultado será field1<space><tab><space>field2, (porque ele usará delimitador de espaço em branco por padrão) ao contrário do field1<tab>field2que provavelmente é o que você está esperando. usar o separador de campo de saída (OFS) é quase sempre o que você deseja.
DryLabRebel

13
awk '{print $NF-1, $NF}'  inputfile

Nota: isso funciona apenas se houver pelo menos duas colunas. Em registros com uma coluna, você obterá um espúrio"-1 column1"


3
Experimente e veja. Ele funciona no Solaris 9 awk e nawk. A alternativa é $ (NF-1)
jim mcnamara

1
@coaddict - Suponho que você não trabalhou com diferentes implementações do awk. Antigos comportamentos de awks foram (talvez erroneamente) apresentados. Não tenho gawk para testar - que é provavelmente o que você está se referindo. Portanto, não sei ao certo por que seu comentário veio abnput. O Linux fora da caixa geralmente é estúpido. Vou testar e postar de volta. Enquanto isso, tente Soalris ou HPUX ou DGX ou qualquer outra coisa para ver o que quero dizer com antigo awk.
Jim Mcnamara

6
Você provavelmente foi levado a pensar que funcionou porque tentou echo 1 2 3 | awk .... $NF-1está ($NF) - 1em cada awkimplementação.
Stephane Chazelas

O código-fonte "One True Awk" tem mais de 40 conflitos na yaccgramática, o que é irônico dado o que o A significa em awk. Versões diferentes do awk analisando as coisas de maneira diferente? Grande surpresa!
Kaz

1
@THESorcerer, tente com echo '5 4 3 2 1' | awk '{print $NF-1,$NF; print $(NF-1), $NF}'- ou qualquer outra entrada onde o segundo último campo não seja um a menos que o último campo.
glenn jackman

6

@jim mcnamara: tente usar parênteses ao redor NF, ou seja, $(NF-1)e ao $(NF)invés de $NF-1e $NF(funciona no Mac OS X 10.6.8 para FreeBSD awke gawk).

echo '
1 2
2 3
one
one two three
' | gawk '{if (NF >= 2) print $(NF-1), $(NF);}'

# output:
# 1 2
# 2 3
# two three

Já havíamos considerado () anteriormente. Achei que estávamos discutindo de onde veio o antigo comportamento original do awk.
Jim Mcnamara,

+1 para uma resposta com explícito $(NF-1)- que no mínimo é mais portátil do que $NF-1; é definitivamente menos ambíguo. $(NF)é um exagero - apenas $NFservirá. Também vale a pena se proteger contra linhas com menos de 2 colunas, pois com linhas de uma coluna você obteria o valor da primeira coluna duas vezes , e com linhas zero - ou seja, vazias - o comando awk falharia completamente, devido a uma tentativa para acessar um campo com índice -1.
mklement0

1

usar o gawk exibe o problema:

 gawk '{ print $NF-1, $NF}' filename
1 2
2 3
-1 one
-1 three
# cat filename
1 2
2 3
one
one two three

Acabei de colocar gawk no Solaris 10 M4000: Então, gawk é o cuplrit na questão $ NF-1 vs. $ (NF-1). Próxima pergunta, o que POSIX diz? por:

http://www.opengroup.org/onlinepubs/009695399/utilities/awk.html

Não há direção de um jeito ou de outro. Não é bom. gawk implica subtração, outros awks implicam número de campo ou subtração. Hmm.


1
As primeiras 2 linhas de seu arquivo de entrada de amostra não são úteis porque produzem a mesma saída com qualquer um dos comportamentos. Você pode reconfirmar que o Solaris awk realmente NÃO se comporta como gawk neste caso?
mklement0

Quanto ao seu link para a especificação do awk: O argumento anedótico para usar $(NF-1)é que os dois exemplos de cálculo do índice de campo na especificação usam essa forma: $(NF-1)e $(NF+2). Depois, há a seção "Expressões no awk", que lista os $exprnomes com precedência [muito] maior do que expr - expr. Uma vez que NFé uma expressão em si, $NF-1deve avaliar como ($NF)-1. Mesmo se, afinal, houver implementações awk por aí que avaliam $NF-1como $(NF-1), a lição aprendida aqui é que usar $(NF-1)é a escolha segura e portátil.
mklement0

0

tente com isso

$ cat /tmp/topfs.txt
/dev/sda2      xfs        32G   10G   22G  32% /

awk print last column
$ cat /tmp/topfs.txt | awk '{print $NF}'

awk print before last column
$ cat /tmp/topfs.txt | awk '{print $(NF-1)}'
32%

awk - print last two columns
$ cat /tmp/topfs.txt | awk '{print $(NF-1), $NF}'
32% /

0

Tente fazer isso levando em consideração todos os cenários possíveis:

awk '{print $(NF-1)"\t"$NF}'  file

ou

awk 'BEGIN{OFS="\t"}' file

ou

awk '{print $(NF-1), $NF} {print $(NF-1), $NF}' file
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.