utilizzando awk con condizioni di valore di colonna


108

Sto imparando awk da The AWK Programming Language e ho un problema con uno degli esempi.

Se volessi stampare $ 3 se $ 2 è uguale a un valore (ad esempio 1), stavo usando questo comando che funziona bene:

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

Ma quando sostituisco 1 con un altro criterio di ricerca, (ad esempio findtext), il comando non funziona:

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

Non restituisce alcun output e sono sicuro che "findtext" esista nel file di input.

Ho provato anche questo, ma non funziona:

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

Ecco il mio file di test chiamato 'test' e ha 9 righe e 8 campi, separati da spazio:

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

Ecco cosa ho fatto e l'output:

$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

Mi aspetto di vedere questo che è il $ 3 che ha "ClNonZ" nei loro $ 8.

0.180467091 
0.010615711 
0.492569002

Non so perché il comando awk non ha restituito nulla. qualche idea?


Devi citare il valore della stringa "findtext", altrimenti è un nome di variabile
male otto

Ho provato le virgolette doppie con "findtext", ma non funziona .. ecco perché mi dà fastidio
user1687130

1
"Non funziona" non ci dice niente. Mostraci input esatti, codice esatto, output previsto e output effettivo.
chepner

Risposte:


128

Se stai cercando una stringa particolare, racchiudila tra virgolette:

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

Altrimenti, awk presumerà che sia un nome di variabile.


Ho provato questo ma non funziona, non so perché. Ho ricontrollato con grep e il testo era lì. :(
user1687130

1
@ user1687130, penso che dovrai mostrarci alcuni input di esempio e output attesi.
Carl Norum

1
Sei sicuro che i tuoi dati siano separati da spazi. Alcuni di questi spazi potrebbero essere tabulazioni? Prova a usare awk per riprodurre un singolo campo. Ti awk '{ print $8 }'dà quello che ti aspetteresti?
Rob Davis

1
Potrebbe essere a causa di AWKimplementazione (controllare con awk --version), date un'occhiata alla mia risposta, funziona in GAWKe MAWKtroppo.
arutaku

Questo non funziona quando usiamo virgolette doppie attorno allo script awk. Mi piaceawk "$1 == \"findtext\" {print $3}"
Thirupathi Thangavel,

33

Questo metodo utilizza regexp, dovrebbe funzionare:

awk '$2 ~ /findtext/ {print $3}' <infile>

Grazie stavo cercando un modo per usare awk per trovare regex su $ NF senza usare metodi diabolici e grep ^^
Thibault Loison

20

A seconda AWKdell'implementazione che stai usando ==va bene o no.

Hai provato ~? Ad esempio, se vuoi che $ 1 sia "ciao":

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

^significa $ 1 inizio ed $è $ 1 fine.


4
Tutte le implementazioni di awk supportano sia "==" che "~".
Ed Morton

2
@EdMorton - OS X awknon è riuscito ad abbinare ==, ma è riuscito con ~.
jww

2
@jww Impossibile abbinare cosa con cosa? Questi sono equivalenti: $1 == "hello"e $1 ~ /^hello$/. Non dovresti mai fare $1 ~ "^hello$"come mostrato in questa risposta poiché utilizza una stringa in un contesto regexp e quindi awk deve convertire la stringa in una regexp prima di usarla e questo ha effetti collaterali (man awk).
Ed Morton

4

Questo è più leggibile per me

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

2

La mia versione di awk è 3.1.5.

Sì, il file di input è separato da spazi, senza tabulazioni.

Secondo la risposta di arutaku, ecco cosa ho provato che ha funzionato:

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


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

Cosa non ha funzionato (non so perché e forse a causa della mia versione awk :),

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

Grazie a tutti per le vostre risposte, commenti e aiuto!


9
Questo non ha nulla a che fare con la tua versione di awk. Hai creato il tuo file di test su Windows, quindi qualunque strumento tu abbia usato per farlo ha aggiunto control-Ms alla fine di ogni riga, quindi l'ultimo campo su ogni riga è ClNonZ<control-M>, non ClNonZè per questo che un confronto di corrispondenza parziale RE come fatto con grep o "~ "in awk lo trova ma un confronto di uguaglianza no.
Ed Morton

2
Sì, ha un senso. Ho provato $ dos2unix test e poi ho usato "==" per sostituire "~" e funziona. Grazie per la spiegazione!
user1687130

-3

per favore prova questo

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

o

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

Purtroppo questa risposta non utilizza effettivamente la sintassi Awk che l'utente ha specificamente richiesto!
Asfand Qazi
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.