menggunakan awk dengan kondisi nilai kolom

108

Saya belajar awk dari The AWK Programming Language dan saya punya masalah dengan salah satu contohnya.

Jika saya ingin mencetak $ 3 jika $ 2 sama dengan nilai (misalnya 1), saya menggunakan perintah ini yang berfungsi dengan baik:

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

Tetapi ketika saya mengganti 1 dengan kriteria pencarian lain, (misalnya findtext), perintahnya tidak berfungsi:

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

Itu tidak mengembalikan output dan saya yakin bahwa 'findtext' ada di file input.

Saya juga mencoba ini, tetapi tidak berhasil:

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

Ini file pengujian saya bernama 'test' dan memiliki 9 baris dan 8 bidang, dipisahkan oleh spasi:

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

Inilah yang saya lakukan dan hasilnya:

$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

Saya berharap untuk melihat ini yang merupakan $ 3 yang memiliki "ClNonZ" di $ 8 mereka.

0.180467091 
0.010615711 
0.492569002

Tidak tahu mengapa perintah awk tidak mengembalikan apapun. Ada pemikiran?

pengguna1687130
sumber
Anda perlu mengutip nilai string "findtext", jika tidak, itu adalah nama variabel
evil otto
Saya mencoba tanda kutip ganda dengan "findtext", tetapi tidak berhasil .. itulah mengapa mengganggu saya
user1687130
1
"Tidak berhasil" tidak memberi tahu kita apa pun. Tunjukkan kepada kami masukan yang tepat, kode yang tepat, keluaran yang diharapkan, dan keluaran yang sebenarnya.
chepner

Jawaban:

128

Jika Anda mencari string tertentu, berikan tanda kutip di sekitarnya:

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

Jika tidak, awk akan menganggap itu nama variabel.

Rob Davis
sumber
Saya mencoba ini tetapi tidak berhasil. Saya tidak tahu mengapa. Saya memeriksa ulang dengan grep dan teksnya ada di sana. :(
user1687130
1
@ user1687130, saya rasa Anda perlu menunjukkan beberapa contoh masukan dan keluaran yang diharapkan.
Carl Norum
1
Apakah Anda yakin data Anda dipisahkan spasi. Mungkinkah beberapa dari spasi itu menjadi tab? Coba gunakan awk untuk menggemakan satu bidang. Apakah awk '{ print $8 }'memberi Anda apa yang Anda harapkan?
Rob Davis
1
Mungkin karena AWKimplementasi (periksa dengan awk --version), lihat jawaban saya, itu berfungsi GAWKdan MAWKjuga.
arutaku
Ini tidak berfungsi saat kami menggunakan tanda kutip ganda di sekitar skrip awk. Sepertiawk "$1 == \"findtext\" {print $3}"
Thirupathi Thangavel
33

Metode ini menggunakan regexp, seharusnya berfungsi:

awk '$2 ~ /findtext/ {print $3}' <infile>
Elo
sumber
Terima kasih, saya sedang mencari cara menggunakan awk untuk menemukan regex di $ NF tanpa menggunakan metode jahat dan grep ^^
Thibault Loison
20

Tergantung pada AWKimplementasinya, apakah yang Anda gunakan ==ok atau tidak.

Sudahkah Anda mencoba ~? Misalnya, jika Anda ingin $ 1 menjadi "halo":

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

^berarti $ 1 awal, dan $$ 1 akhir.

arutaku
sumber
4
Semua implementasi awk mendukung "==" dan "~".
Ed Morton
2
@EdMorton - OS X awkgagal untuk dicocokkan ==, tetapi berhasil dengan ~.
jww
2
@jww Gagal mencocokkan apa dengan apa? Ini setara: $1 == "hello"dan $1 ~ /^hello$/. Anda tidak boleh melakukan $1 ~ "^hello$"seperti yang ditunjukkan dalam jawaban ini karena menggunakan string dalam konteks regexp dan awk harus mengonversi string menjadi regexp sebelum menggunakannya dan itu memiliki efek samping (man awk).
Ed Morton
4

Ini lebih mudah dibaca untuk saya

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

Versi awk saya adalah 3.1.5.

Ya, file masukan dipisahkan spasi, tidak ada tab.

Menurut jawaban arutaku, inilah yang saya coba yang berhasil:

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


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

Apa yang tidak berhasil (saya tidak tahu mengapa dan mungkin karena versi awk saya :),

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

Terima kasih atas jawaban, komentar, dan bantuan Anda!

pengguna1687130
sumber
9
Ini tidak ada hubungannya dengan versi awk Anda. Anda membuat file uji Anda di Windows jadi alat apa pun yang Anda gunakan untuk melakukan itu menambahkan kontrol-Ms ke akhir setiap baris sehingga bidang terakhir pada setiap baris adalah ClNonZ<control-M>, bukan ClNonZitu sebabnya perbandingan pencocokan parsial RE seperti yang dilakukan dengan grep atau "~ "di awk menemukannya tetapi perbandingan kesetaraan tidak.
Ed Morton
2
Ya, masuk akal. Saya mencoba tes $ dos2unix dan kemudian menggunakan "==" untuk menggantikan "~" dan berhasil. Terima kasih untuk penjelasannya!
pengguna1687130
-3

silahkan coba ini

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

atau

echo cat filename | grep ClNonZ | awk '{print $3}';
Mustafa
sumber
Sayangnya jawaban ini tidak benar-benar menggunakan sintaks Awk yang secara khusus diminta oleh pengguna!
Asfand Qazi