Saya ingin menjalankan skrip gawk dengan --re-interval
menggunakan shebang. Pendekatan "naif" dari
#!/usr/bin/gawk --re-interval -f
... awk script goes here
tidak berfungsi, karena gawk dipanggil dengan argumen pertama "--re-interval -f"
(tidak dipisahkan di sekitar spasi), yang tidak dipahami. Apakah ada solusi untuk itu?
Tentu saja Anda tidak dapat memanggil gawk secara langsung tetapi membungkusnya ke dalam skrip shell yang memisahkan argumen pertama, atau membuat skrip shell yang kemudian memanggil gawk dan memasukkan skrip ke file lain, tetapi saya bertanya-tanya apakah ada cara untuk melakukannya ini dalam satu file.
Perilaku baris shebang berbeda dari satu sistem ke sistem lainnya - setidaknya di Cygwin tidak membagi argumen dengan spasi. Saya hanya peduli tentang bagaimana melakukannya pada sistem yang berperilaku seperti itu; skrip tidak dimaksudkan untuk dibawa-bawa.
--re-interval
tidak diperlukan lagi (lihat [ gnu.org/software/gawk/manual/… ).Jawaban:
Ini sepertinya berhasil untuk saya dengan (g) awk.
Perhatikan
#!
prosesnya/bin/sh
, jadi skrip ini pertama kali diinterpretasikan sebagai skrip shell.Pada awalnya, saya hanya mencoba
"exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@"
, tetapi canggung memperlakukannya sebagai perintah dan mencetak setiap baris input tanpa syarat. Itulah mengapa saya memasukkanarbitrary_long_name==0
- itu seharusnya gagal sepanjang waktu. Anda bisa menggantinya dengan beberapa string omong kosong. Pada dasarnya, saya mencari kondisi palsu di awk yang tidak akan mempengaruhi skrip shell.Dalam skrip shell,
arbitrary_long_name==0
definisikan variabel yang dipanggilarbitrary_long_name
dan setel sama dengan=0
.sumber
bash
, atau akankah berfungsi dengan POSIX apa punsh
? Dan saya tidakawk
sering menggunakannya , jadi saya tidak yakin trik saya di baris kedua adalah cara yang baik untuk memaksaawk
mengabaikan baris.arbitrary_long_name
tidak berbenturan dengan variabel yang digunakan dalam program awk yang sebenarnya, saya tidak dapat melihat masalah apa pun. Apakah ada sesuatu yang saya lewatkan?#!/bin/sh -
alih-alih#!/bin/sh
untuk melindungi skrip dari kemungkinan berperilaku buruk dengan cara yang berbahaya jika dipanggil dengan argumen ke nol yang dimiliki-
sebagai karakter pertama. Hal ini dapat terjadi secara tidak sengaja dalam bahasa pemrograman seperti C, di mana mudah untuk secara tidak sengaja mengacaukan dengan lupa meneruskan nama program yang dipanggil sebagai bagian dari array argumen keexecve
dan fungsi serupa, dan jika orang biasanya lupa untuk melindunginya, itu juga bisa akhirnya menjadi langkah terakhir dalam kerentanan yang dapat dieksploitasi secara jahat yang memungkinkan penyerang mendapatkan shell interaktif.Garis shebang tidak pernah ditentukan sebagai bagian dari POSIX, SUS, LSB atau spesifikasi lainnya. AFAIK, bahkan belum terdokumentasi dengan baik.
Ada konsensus kasar tentang apa yang dilakukannya: mengambil segala sesuatu antara the
!
dan the\n
danexec
itu. Asumsinya adalah bahwa segala sesuatu antara the!
dan the\n
adalah jalur absolut penuh ke penafsir. Tidak ada konsensus tentang apa yang terjadi jika itu berisi spasi.Untungnya, 1. dan 4. tampaknya telah mati, tetapi 3. cukup tersebar luas, jadi Anda tidak bisa mengandalkan kemampuan untuk menyampaikan lebih dari satu argumen.
Dan karena lokasi perintah juga tidak ditentukan dalam POSIX atau SUS, Anda umumnya menggunakan up yang argumen tunggal dengan melewati executable nama untuk
env
sehingga hal itu dapat menentukan lokasi executable; misalnya:[Jelas, ini masih mengasumsikan jalur tertentu untuk
env
, tetapi hanya ada sedikit sistem di mana ia hidup/bin
, jadi ini umumnya aman. Lokasienv
jauh lebih terstandarisasi daripada lokasigawk
atau bahkan lebih buruk sepertipython
atauruby
atauspidermonkey
.]Artinya, Anda tidak dapat benar-benar menggunakan argumen apa pun sama sekali .
sumber
-S
sakelar yang membantu di sini, tetapi tidak ada di Linux sayaenv
, dan saya curiga juga tidak tersedia di gygwin. @hstoerr, pengguna lain dengan situasi berbeda mungkin membaca pertanyaan Anda nanti, jadi secara umum jawaban portabel lebih disukai, bahkan jika Anda sekarang tidak memerlukan portabilitas.#!/bin/sh
dan/usr/bin/env gawk --re-interval -f my-script.awk
. Apakah itu benar?#!
itu sendiri tidak portabel. Misalnya, Windows sama sekali tidak mengenali konvensi ini "secara asli". Sebuah argumen yang kuat diperlukan pada Unix secara tradisional untuk dapat melakukannya#!/usr/bin/awk -f
.#!/usr/bin/env ruby
atau like.Meskipun tidak terlalu portabel, dimulai dengan coreutils 8.30 dan menurut dokumentasinya, Anda akan dapat menggunakan:
Jadi diberikan:
kamu akan mendapatkan:
dan jika Anda penasaran
showargs
adalah:Jawaban asli di sini .
sumber
Saya menemukan masalah yang sama, tanpa solusi yang jelas karena cara spasi putih ditangani dalam shebang (setidaknya di Linux).
Namun, Anda dapat memberikan beberapa opsi dalam shebang, selama opsi tersebut pendek dan dapat digabungkan (dengan cara GNU).
Misalnya, Anda tidak dapat memiliki
tapi kamu bisa
Jelas, itu hanya berfungsi ketika opsinya memiliki padanan pendek dan tidak mengambil argumen.
sumber
Di bawah Cygwin dan Linux semuanya setelah jalur shebang diurai ke program sebagai satu argumen.
Dimungkinkan untuk meretas ini dengan menggunakan
awk
skrip lain di dalam shebang:Ini akan dieksekusi
{system("/usr/bin/gawk --re-interval -f " FILENAME); exit}
dalam awk.Dan ini akan dijalankan
/usr/bin/gawk --re-interval -f path/to/your/script.awk
di shell sistem Anda.sumber
Trik shell shebang di atas lebih portabel daripada
/usr/bin/env
.sumber
python
, tetapi pertanyaan ini adalah tentangawk
.Dalam manual gawk (http://www.gnu.org/manual/gawk/gawk.html), di akhir bagian 1.14 perhatikan bahwa Anda hanya boleh menggunakan satu argumen saat menjalankan gawk dari baris shebang. Dikatakan bahwa OS akan memperlakukan semuanya setelah jalan melongo sebagai argumen tunggal. Mungkin ada cara lain untuk menentukan file
--re-interval
opsi? Mungkin skrip Anda dapat mereferensikan shell Anda di baris shebang, dijalankangawk
sebagai perintah, dan menyertakan teks skrip Anda sebagai "dokumen di sini".sumber
gawk
, tetapi Anda mungkin masih dapat menyalurkan sesuatu di lebih dari stderr (yaitu, alihkan stdout ke stderr sebelum menyalurkan ke skrip ini). Saya belum pernah benar-benar mencobanya tetapi selama proses pertama tidak mengeluarkan apa pun di stderr, itu mungkin berhasil. Anda juga dapat membuat pipa bernama ( linuxjournal.com/content/using-named-pipes-fifos-bash ) jika Anda ingin memastikan tidak ada orang lain yang menggunakannya.Mengapa tidak menggunakan
bash
dangawk
dirinya sendiri, untuk melewati shebang, membaca skrip, dan meneruskannya sebagai file ke contoh keduagawk [--with-whatever-number-of-params-you-need]
?(-yang sama secara alami juga dapat dicapai dengan misalnya
sed
atautail
, tetapi saya pikir ada semacam keindahan yang hanya bergantung padabash
dangawk
dirinya sendiri;)sumber
Hanya untuk kesenangan: ada solusi yang cukup aneh berikut yang mengubah rute stdin dan program melalui deskriptor file 3 dan 4. Anda juga dapat membuat file sementara untuk skrip.
Satu hal yang mengganggu tentang ini: shell melakukan ekspansi variabel pada skrip, jadi Anda harus mengutip setiap $ (seperti yang dilakukan di baris kedua skrip) dan mungkin lebih dari itu.
sumber
Untuk solusi portabel, gunakan
awk
daripadagawk
, panggil BOURNE shell (/bin/sh
) standar dengan shebang Anda, dan panggilawk
secara langsung, meneruskan program pada baris perintah sebagai dokumen di sini daripada melalui stdin:Catatan: tidak ada
-f
argumen untukawk
. Yang meninggalkanstdin
tersedia untukawk
membaca masukan dari. Dengan asumsi Anda telahgawk
menginstal dan pada AndaPATH
, itu mencapai semua yang saya pikir Anda coba lakukan dengan contoh asli Anda (dengan asumsi Anda ingin konten file menjadi skrip awk dan bukan input, yang menurut saya pendekatan shebang Anda akan memperlakukannya sebagai ).sumber