usando awk con condiciones de valor de columna

108

Estoy aprendiendo awk del lenguaje de programación AWK y tengo un problema con uno de los ejemplos.

Si quisiera imprimir $ 3 si $ 2 es igual a un valor (por ejemplo 1), estaba usando este comando que funciona bien:

awk '$2==1 {print $3}' <infile> | more

Pero cuando sustituyo 1 por otro criterio de búsqueda, (por ejemplo findtext), el comando no funciona:

awk '$1== findtext {print $3}' <infile> | more

No devuelve ninguna salida y estoy seguro de que 'findtext' existe en el archivo de entrada.

También probé esto, pero no funciona:

awk '$1== "findtext" {print $3}' <infile> | more

Aquí está mi archivo de prueba llamado 'prueba' y tiene 9 líneas y 8 campos, separados por espacio:

1 11 0.959660297 0 0.021231423 -0.0073 -0.0031 MhZisp
2 14 0.180467091 0.800424628 0 0.0566 0.0103 ClNonZ
3 19 0.98089172 0 0 -0.0158 0.0124 MhNonZ
4 15 0.704883227 0.265392781 0.010615711 -0.0087 -0.0092 MhZisp
5 22 0.010615711 0.959660297 0.010615711 0.0476 0.0061 ClNonZ
6 23 0.715498938 0 0.265392781 -0.0013 -0.0309 Unkn
7 26 0.927813163 0 0.053078556 -0.0051 -0.0636 MhZisp
8 44 0.55626327 0.222929936 0.201698514 0.0053 -0.0438 MhZisp
9 31 0.492569002 0.350318471 0.138004246 0.0485 0.0088 ClNonZ

Esto es lo que hice y el resultado:

$awk '$8 == "ClNonZ" {print $3}' test 

$ grep ClNonZ test 
2 14 0.180467091 0.800424628 0 0.0566 0.0103 ClNonZ
5 22 0.010615711 0.959660297 0.010615711 0.0476 0.0061 ClNonZ
9 31 0.492569002 0.350318471 0.138004246 0.0485 0.0088 ClNonZ

Espero ver esto, que son los $ 3 que tienen "ClNonZ" en sus $ 8.

0.180467091 
0.010615711 
0.492569002

No sé por qué el comando awk no devolvió nada. ¿Alguna idea?

user1687130
fuente
Debe citar el valor de la cadena "findtext", de lo contrario es un nombre de variable
otto malvado
Intenté comillas dobles con "findtext", pero no funciona ... por eso me molesta
user1687130
1
"No funciona" no nos dice nada. Muéstrenos entradas exactas, código exacto, salida esperada y salida real.
chepner

Respuestas:

128

Si está buscando una cadena en particular, colóquela entre comillas:

awk '$1 == "findtext" {print $3}'

De lo contrario, awk asumirá que es un nombre de variable.

Rob Davis
fuente
Intenté esto pero no funciona, no sé por qué. Verifiqué dos veces con grep y el texto estaba allí. :(
user1687130
1
@ user1687130, creo que necesitará mostrarnos algunos ejemplos de entrada y salida esperada.
Carl Norum
1
¿Estás seguro de que tus datos están separados por espacios? ¿Algunos de esos espacios podrían ser pestañas? Intente usar awk para hacer eco de un solo campo. ¿ awk '{ print $8 }'Te da lo que esperabas?
Rob Davis
1
Puede deberse a la AWKimplementación (compruébelo con awk --version), eche un vistazo a mi respuesta, funciona en GAWKy MAWKtambién.
arutaku
Esto no funciona cuando usamos comillas dobles alrededor del script awk. Me gustaawk "$1 == \"findtext\" {print $3}"
Thirupathi Thangavel
33

Este método usa regexp, debería funcionar:

awk '$2 ~ /findtext/ {print $3}' <infile>
Ana
fuente
Gracias, estaba buscando una forma de usar awk para encontrar expresiones regulares en $ NF sin usar métodos diabólicos y grep ^^
Thibault Loison
20

Dependiendo de la AWKimplementación que esté utilizando, ==está bien o no.

¿Lo has probado ~?. Por ejemplo, si quieres que $ 1 sea "hola":

awk '$1 ~ /^hello$/{ print $3; }' <infile>

^significa $ 1 comienzo y $es $ 1 final.

arutaku
fuente
4
Todas las implementaciones de awk admiten tanto "==" como "~".
Ed Morton
2
@EdMorton - OS X awkno pudo coincidir ==, pero tuvo éxito con ~.
jww
2
@jww ¿No pudo emparejar qué con qué? Estos son equivalentes: $1 == "hello"y $1 ~ /^hello$/. Nunca debe hacer lo $1 ~ "^hello$"que se muestra en esta respuesta, ya que está usando una cadena en un contexto regexp y, por lo tanto, awk tiene que convertir la cadena en una expresión regular antes de usarla y eso tiene efectos secundarios (man awk).
Ed Morton
4

Esto es más legible para mí

awk '{if ($2 ~ /findtext/) print $3}' <infile>
usuario2773013
fuente
2

Mi versión de awk es 3.1.5.

Sí, el archivo de entrada está separado por espacios, sin pestañas.

De acuerdo con la respuesta de arutaku, esto es lo que probé y funcionó:

awk '$8 ~ "ClNonZ"{ print $3; }' test  
0.180467091
0.010615711
0.492569002


$ awk '$8 ~ "ClNonZ" { print $3}' test  
0.180467091
0.010615711
0.492569002

Qué no funcionó (no sé por qué y tal vez debido a mi versión awk :),

$awk '$8 ~ "^ClNonZ$"{ print $3; }' test
$awk '$8 == "ClNonZ" { print $3 }' test

¡Gracias a todos por sus respuestas, comentarios y ayuda!

user1687130
fuente
9
Esto no tiene nada que ver con tu versión awk. Creó su archivo de prueba en Windows, así que cualquier herramienta que usó para hacer eso agregó control-Ms al final de cada línea para que el último campo en cada línea sea ClNonZ<control-M>, no ClNonZes por eso que una comparación de coincidencia parcial de RE como se hace con grep o "~ "en awk lo encuentra pero una comparación de igualdad no.
Ed Morton
2
Sí, tiene sentido. Probé la prueba $ dos2unix y luego usé "==" para reemplazar "~" y funciona. ¡Gracias por la explicación!
user1687130
-3

por favor intente esto

echo $VAR | grep ClNonZ | awk '{print $3}';

o

echo cat filename | grep ClNonZ | awk '{print $3}';
Mustafa
fuente
Lamentablemente, esta respuesta en realidad no usa la sintaxis Awk que el usuario solicitó específicamente.
Asfand Qazi