Cómo imprimir las dos últimas columnas usando awk

106

Todo lo que quiero son las dos últimas columnas impresas.

vehomzzz
fuente
6
No estoy muy seguro de por qué esto tiene 87 votos a favor, ciertamente se puede mejorar con un ejemplo al menos.
Arj
Probablemente porque la pregunta es extremadamente simple por naturaleza y fácil de entender sin un ejemplo, lo cual es raro, pero en este caso parece funcionar. El problema aquí no es la falta de información, creo, sino más bien muestra una falta de investigación independiente.
DryLabRebel
Esta pregunta también es un duplicado de esta pregunta.
DryLabRebel
¿Responde esto a tu pregunta? Imprima la penúltima columna / campo en awk
DryLabRebel

Respuestas:

194

Puede hacer uso de la variable NFque se establece en el número total de campos en el registro de entrada:

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

esto supone que tiene al menos 2 campos.

codaddict
fuente
1
Necesita una coma, ya que hoy somos exigentes: el espacio concatena los campos, la coma los separa en una declaración de impresión. Eso fusionará los dos campos
jim mcnamara
18
Ahora está imprimiendo "field-OFS-tab-OFS-field". Debería ser awk '{print $(NF-1) "\t" $NF}' fileo awk '{print $(NF-1), $NF}' fileo awk 'BEGIN{OFS="\t"} {print $(NF-1), $NF}' file.
Pausado hasta nuevo aviso.
Solo para agregar al comentario anterior, el problema con el uso '{print $x,"\t",$y}'es que awk interpreta cada variable separada por comas como su propio campo, por lo que el resultado será en realidad field1<space><tab><space>field2, (porque usará el delimitador de espacios en blanco de forma predeterminada) en lugar de lo field1<tab>field2que probablemente sea lo que estás esperando. usar el Separador de campo de salida (OFS) es casi siempre lo que desea.
DryLabRebel
13
awk '{print $NF-1, $NF}'  inputfile

Nota: esto solo funciona si existen al menos dos columnas. En registros con una columna obtendrá un falso"-1 column1"

jim mcnamara
fuente
3
Prueba y verás. Funciona Solaris 9 awk & nawk. La alternativa es $ (NF-1)
jim mcnamara
1
@coaddict: supongo que no ha trabajado con diferentes implementaciones de awk. Se han presentado (quizás erróneamente) comportamientos antiguos de awks. No tengo la boca abierta para probar, que es probablemente a lo que te refieres. Así que no sé con certeza por qué su comentario fue incorrecto. Linux awk listo para usar generalmente es boquiabierto. Lo probaré y lo publicaré. Mientras tanto, pruebe con Soalris o HPUX o DGX o lo que sea para ver lo que quiero decir con awk antiguo.
jim mcnamara
6
Probablemente te engañaron para que pensaras que funcionó porque lo intentaste echo 1 2 3 | awk .... $NF-1está ($NF) - 1en cada awkimplementación.
Stephane Chazelas
El código fuente de "One True Awk" tiene más de 40 conflictos en la yaccgramática, lo cual es irónico dado lo que la A significa en awk. ¿Diferentes versiones de awk analizando las cosas de manera diferente? ¡Gran sorpresa!
Kaz
1
@THESorcerer, intente con echo '5 4 3 2 1' | awk '{print $NF-1,$NF; print $(NF-1), $NF}'- o cualquier otra entrada donde el segundo último campo no sea uno menos que el último campo.
Glenn Jackman
6

@jim mcnamara: intente usar paréntesis para alrededor NF, es decir, $(NF-1)y en $(NF)lugar de $NF-1y $NF(funciona en Mac OS X 10.6.8 para FreeBSD awky 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
guzo
fuente
Ya habíamos considerado () antes. Pensé que estábamos discutiendo de dónde provenía el antiguo comportamiento awk original.
jim mcnamara
+1 para una respuesta con explícito $(NF-1), que al menos es más portátil que $NF-1; definitivamente es menos ambiguo. $(NF)Sin embargo, es exagerado, solo $NFservirá. También vale la pena protegerse contra las líneas con menos de 2 columnas, ya que con las líneas de una columna obtendría el valor de la primera columna dos veces , y con las líneas de columna cero, es decir, vacías, el comando awk fallaría por completo, debido a un intento para acceder a un campo con índice -1.
mklement0
1

el uso de gawk presenta el 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

Acabo de poner boquiabierto a Solaris 10 M4000: Entonces, gawk es el cuplrit en el problema de $ NF-1 vs. $ (NF-1). Siguiente pregunta ¿qué dice POSIX? por:

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

No hay dirección en un sentido u otro. No está bien. gawk implica resta, otros awks implican número de campo o resta. hmm.

jim mcnamara
fuente
1
Las primeras 2 líneas de su archivo de entrada de muestra no son útiles porque producen la misma salida con cualquier comportamiento. ¿Puede volver a confirmar que Solaris awk NO se comporta como gawk en este caso?
mklement0
En cuanto a su enlace a la especificación awk: el argumento anecdótico para usar $(NF-1)es que los dos ejemplos de cálculo del índice de campo en la especificación usan esa forma: $(NF-1)y $(NF+2). Luego está la sección "Expresiones en awk", que $exprtiene una precedencia [mucho] mayor que expr - expr. Dado que NFes una expresión en sí misma, $NF-1debería evaluarse como ($NF)-1. Incluso SI, después de todo, existen implementaciones de awk que evalúan $NF-1como $(NF-1), la lección aprendida aquí es que usar $(NF-1)es la opción segura y portátil.
mklement0
0

prueba con esto

$ 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% /
namasivayam.cse
fuente
0

Pruebe esto para tener en cuenta todos los escenarios posibles:

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

o

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

o

awk '{print $(NF-1), $NF} {print $(NF-1), $NF}' file
Marios Karamanis
fuente