Gunakan variabel shell di awk

8

Ini skrip saya (untuk menemukan file yang berisi pola tertentu):

find . -type f \
    -exec awk -v vawk="$1" '/'"$vawk"'/ {c++} c>0 { print ARGV[1]; exit 0 } END { if (! c) {exit 1}}' \{\} \;

Saya ingin menggunakan skrip saya dengan argumen §:

MyScript.sh pattern

Masalah saya adalah bahwa saya tidak berhasil memasukkan $1variabel awk.

Ketika saya mencoba men-debug skrip saya

bash -x MyScript.sh pattern

Berikut hasilnya:

+ find . -type f -exec awk -v vawk=pattern '// {c++} c>0 {print ARGV[1] ; exit 0 } END { if (! c) {exit 1}}' '{}' ';'

The $vawkvariabel tampaknya kosong.

Ada ide?

Nicolas
sumber

Jawaban:

7

Anda tampaknya membingungkan variabel awk dan variabel shell. awk -v vawk="$1"membuat variabel awk disebut vawk, namun Anda mencoba menggunakan sintaks shell ( $vawk). Ini tidak berfungsi karena shell tidak memiliki variabel yang dipanggil vawk. Saya pikir apa yang Anda inginkan

awk -v vawk="$1" '$0 ~ vawk { c++ } # ...'
#                      ^ awk variable syntax
jw013
sumber
1
Catatan yang awkmemperluas urutan pelarian seperti-C di $1, sehingga pendekatan tidak bekerja jika $1mungkin berisi karakter garis miring terbalik (umum untuk regexps). Anda dapat menggunakan ENVIRONarray khusus awk sebagai gantinya.
Stéphane Chazelas
6

Direproduksi dari ini sekarang ditutup sebagai pertanyaan rangkap karena mencakup peringatan tentang pembatasan variabel awk yang mungkin berguna.

Sebuah variabel shell hanya itu: sebuah shell variabel . Jika Anda ingin mengubahnya menjadi variabel awk , Anda memerlukan sintaksis seperti:

awk -v x="$x" '$2 == x {print $1}' infile

atau

awk '$2 == x {print $1}' x="$x" infile

Namun, mereka yang mengalami masalah: urutan pelarian diperluas di dalamnya (dan dengan GNU awk4.2 atau lebih tinggi, jika $xdimulai dengan @/dan berakhir /, diperlakukan sebagai jenis variabel regexp ).

Jadi, misalnya jika variabel shell berisi dua karakter garis miring terbalik dan n , variabel awk akan berakhir mengandung karakter baris baru (dan dengan gawk 4.2+, jika mengandung @/foo/, variabel awk akan berisi foodan bertipe regexp).

Pendekatan lain (tetapi yang -vmembutuhkan untuk POSIX awk atau nawk (sebagai lawan dari tahun 1970-an masih ditemukan seperti /bin/awkpada Solaris)) adalah menggunakan variabel lingkungan:

x="$x" awk '$2 == ENVIRON["x"] {print $1}' infile

Pendekatan lain (masih dengan awk yang lebih baru) adalah dengan menggunakan array ARGV di awk:

awk 'BEGIN {x = ARGV[1]; delete ARGV[1]}
  $2 == x {print $1}' "$x" infile
Stéphane Chazelas
sumber