Apakah ada 2 cara untuk mengatur awk vars melalui command line?


10

Saya perhatikan awkcontoh O'Reilly (1997) yang menetapkan variabel awk dengan menyetelnya di baris perintah setelah teks program. Itu berfungsi, tetapi saya tidak dapat menemukan sintaks ini di man / info awk . Apakah saya baru saja melewatkannya; apakah ini sudah habis ...? Satu-satunya sintaks yang saya lihat di manual adalah -vopsi.

awk '/home/{print foo, bar}' foo="cat" bar="dog" /proc/$$/cmdline

Keluaran: cat dog

Jawaban:


11

Ini sebenarnya dalam POSIX awk(tautan ke POSIX 2008, versi sebelumnya juga saya percaya). -vdijelaskan di bagian Opsi , sebaliknya di bagian Operand .

Ada perbedaan antara -vdan melewati tugas di akhir dengan nama file:

  • Dengan -v:

Aplikasi harus memastikan bahwa argumen penugasan berada dalam bentuk yang sama dengan operan penugasan. Penugasan variabel yang ditentukan harus dilakukan sebelum menjalankan program awk, termasuk tindakan yang terkait dengan pola BEGIN (jika ada). Beberapa kemunculan opsi ini dapat ditentukan.

  • Dicampur dengan nama file:

[...] Setiap tugas variabel tersebut harus terjadi sesaat sebelum pemrosesan file berikut , jika ada. Dengan demikian, penugasan sebelum argumen file pertama harus dieksekusi setelah tindakan BEGIN (jika ada), sementara penugasan setelah argumen file terakhir harus terjadi sebelum tindakan END (jika ada). Jika tidak ada argumen file, tugas harus dilakukan sebelum memproses input standar.

Contoh:

$ cat input 
hello
hello
$ awk -v var=one 'BEGIN{print var} /hello/{print var} END{print var}' \
    var=two input var=three input var=four
one
two
two
three
three
four

Wow! Itu menambahkan beberapa titik kontrol yang menarik ... pasti akan berguna. Terima kasih ...
Peter.O

1
Inisial saya "Wow!" masih berlaku, tetapi telah sedikit marah dengan melihat lebih jauh ke jawaban Arcege ... Saya mengujinya dengan file nyata bernama "var = three" ... awkmemberikan prioritasnya menjadi tugas variabel ... Ini memiliki akibat wajar yang besar yaitu Dalam semua kasus ketika nama file memiliki formulir ini, itu akan diabaikan dan variabel akan ditetapkan ... Tampaknya satu-satunya cara untuk menghindari bentrokan ini adalah dengan memastikan bahwa nama file untuk direktori kerja saat ini harus selalu diawali sebelumnya. dengan jalur relatif mereka:./var=three
Peter.O

@ Peter.O, ya, itu juga salah satu alasan -vsintaks diperkenalkan. Anda harus menganggap -vsintaksis sebagai cara yang disukai untuk melakukan tugas, maju.
dubiousjim

@ Peter.O, poin bagus tentang "gotcha" jika nama file adalah tugas variabel yang valid. Jika Anda menggunakan variabel shell yang berisi nama file dan meneruskannya sebagai argumen awk, Anda bisa menggunakan tangkapan berikut:[ "$myfile" == "${myfile#/}" ] && myfile="./$myfile"
Wildcard

4

Ini adalah gaya lama variabel pengaturan eksternal awk. Itu ambigu (bagaimana jika Anda memiliki nama file bernama foo=cat), jadi versi selanjutnya menambahkan -vopsi. Mungkin seharusnya bekerja untuk kompatibilitas ke belakang, tetapi Anda tidak dapat menjamin. Dan seperti yang saya katakan, -vopsi lebih baru, jadi tidak semua versi awkdapat mendukungnya.


Komentar Anda tentang kemungkinan bentrokan nama-file bagus ... Saya sudah mengujinya dan jelas merupakan masalah. Saya telah menulis sedikit lebih banyak di dalamnya dalam komentar atas jawaban Mat .. Bahasa Thansk untuk menyoroti masalah ini (+1)
Peter.O

2
Sebenarnya, seperti dijelaskan dalam [Mat s answer](http://unix.stackexchange.com/a/34258/9537), -v` dan penugasan argumen berbeda ketika mereka berlaku. Juga -vada dalam POSIX dan harus ada di semua kecuali yang paling kuno dari awkimplementasi. Menggunakan ./atau memastikan nama file berisi karakter yang tidak dapat diidentifikasi mungkin merupakan cara yang paling dapat diandalkan untuk disambiguasi.
jw013
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.