AWK - imprime a última coluna junto com o valor vazio

2

Podemos imprimir a última coluna de cada linha em um arquivo usando $NF se não soubermos o último número da coluna.

Mas estou enfrentando dificuldade é a última coluna tem um valor vazio.

Por exemplo, Analisando o comando who

$ who
root     tty1         2018-01-25 09:36
root     pts/0        2018-05-30 07:39 (192.168.1.134)
root     pts/1        2018-05-28 23:12 (192.168.1.134)
root     pts/2        2018-06-01 10:01 (192.168.1.188)

Obtendo resultado:

$ who | awk '{print $NF}'
09:36
(192.168.1.134)
(192.168.1.134)
(192.168.1.188)

Resultado esperado


(192.168.1.134)
(192.168.1.134)
(192.168.1.188)

Deixe-me saber as possibilidades de obter o resultado esperado em uma única linha.

EDIT 1: O cenário acima é apenas um exemplo. Eu não gosto de mudar o delimitador para alcançar o resultado.

EDIT 2: nada (uma linha vazia de saída) das linhas que possuem menos campos que o máximo

    
por msp9011 01.06.2018 / 09:10

4 respostas

5

Para gerar somente a última coluna de linhas com o número máximo de colunas, você pode fazer algo como:

who | awk '
  NF > max  {max = NF; output = ""}
  NF == max {output = output $NF ORS}
  END       {printf "%s", output}'

Para gerar uma linha para cada linha de entrada, mas vazia para linhas que não tenham o número máximo de colunas:

who | awk '
  NF > max {max = NF}
  {n[NR] = NF}
  NF == max {last[NR] = $NF}
  END {for (i = 1; i <= NR; i++) print n[i] == max ? last[i] : ""}'
    
por 01.06.2018 / 09:46
3

Se você deseja o último campo apenas das linhas que têm mais campos, será necessário ler os dados duas vezes: uma para descobrir o maior número de campos e outra para imprimir os campos. Ler apenas uma vez não é suficiente: qualquer linha pode ter mais campos do que os anteriores e não há como saber.

Com awk (observe que o nome do arquivo é dado duas vezes):

awk -vfields=0 'FNR==NR {if (NF > fields) fields=NF; next} 
     NF >= fields { print $NF } NF < fields {print ""}' file file

Se file contiver

foo bar
one two three four
1 2 3
a b c d

isto imprime o quarto campo ou vazio para as linhas que não o têm:


four

d

Isso, obviamente, não funciona com um pipe, você terá que usar um arquivo temporário.

Uma solução alternativa pode armazenar em cache os campos a serem impressos até que uma linha com mais campos apareça, como em a resposta de Stéphane .

    
por 01.06.2018 / 09:42
1

Verifique se o quinto campo corresponde a \(.*\) e imprima se tiver.

who | awk '$5 ~ /\(.*\)/{print $5}'

Se você estiver interessado apenas em ip endereços, altere o regex:

who |  awk '$5 ~ /\((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\)/{print $5}'
    
por 01.06.2018 / 09:38
0

Se você deseja apenas obter a última coluna, se esta coluna estiver disponível, use o fato de que as linhas que você não quer têm apenas quatro colunas:

who | awk 'NF > 4 { print $NF }'

ou, para obter dados semelhantes,

w -hi | awk '{ print $3 }'
    
por 01.06.2018 / 09:25