Mendistribusikan skrip: Haruskah saya menggunakan / bin / gawk atau / usr / bin / gawk untuk shebang?

12

Apakah biasanya gawk di / bin atau / usr / bin? Saya akan pergi dengan #!/usr/bin/env gawktetapi kemudian saya tidak bisa menggunakan argumen. Saat ini saya sedang menggunakan #!/bin/gawk -f. Scriptnya sangat panjang dan berisi banyak tanda kutip tunggal dan bekerja dengan stdin.

Manual GNU Awk memiliki bagian 1.1.4 Program awk yang dapat dijalankan di mana ia menggunakan #! / Bin / awk dalam contohnya tetapi selanjutnya mengatakan:

Perhatikan bahwa pada banyak sistem awkdapat ditemukan /usr/binalih-alih pada /bin. Caveat Emptor.

Apa yang dilakukan kebanyakan orang? Saya telah membaca sed seharusnya standar di / bin sedangkan perl seharusnya standar di / usr / bin (halaman yang sama dengan tautan sed tetapi mereka tidak akan membiarkan saya membuat tautan ketiga untuk posting ini). Bagaimana dengan awk / gawk? Adakah yang tahu yang lebih umum atau populer?

pengguna2672807
sumber
Mengapa Anda menggunakan -f? Tidak /bin/gawkcukup? Juga, ini mungkin relevan.
terdon

Jawaban:

7

Shebang tidak seharusnya fleksibel . Mungkin ada beberapa kasus di mana parameter kedua berfungsi , saya pikir FreeBSD adalah salah satunya.

melongo dan paling utilitas yang datang dengan OS diharapkan dalam /usr/bin/.

Pada hari-hari UNIX yang lebih lama, sudah biasa untuk /usr/dipasang di NFS atau media yang lebih murah untuk menghemat ruang disk lokal dan biaya per workstation. /bin/seharusnya memiliki semua yang diperlukan untuk boot dalam mode pengguna tunggal . Karena /usr/tidak dipasang pada media yang andal, /bin/termasuk cukup banyak utilitas untuk membuatnya cukup ramah untuk administrasi umum dan pemecahan masalah.

Awalnya ini diwarisi di Linux, tetapi karena ruang disk tidak lagi menjadi masalah dan dalam kebanyakan kasus /usr/ada di sistem file root, tren saat ini adalah untuk memindahkan semuanya /usr/bin(setidaknya di dunia Linux). Jadi sebagian besar utilitas yang dipasang oleh distro diharapkan dapat ditemukan di sana. Bahkan yang paling utilitas dasar, seperti cp, rm, lsdll (baik, belum).

Mengenai pilihan shebang. Secara tradisional, ini adalah sesuatu yang harus diedit oleh admin atau pengguna sesuai dengan lingkungannya. Untuk semua yang diketahui pengembang, dalam sistem orang lain, penerjemah bisa berada di mana saja di sistem file (mis. /usr/local/bin, /opt/gawk-4.0.1/bin). Skrip yang dikemas dengan benar (rpm, deb, dll.) Datang dengan ketergantungan pada paket distro (mis. Penerjemah memiliki lokasi yang diketahui) atau skrip konfigurasi yang mengatur hashbang yang tepat selama instalasi.

forcefsck
sumber
14

Jika Anda tidak perlu meneruskan argumen ke perintah maka itu #!/usr/bin/env gawkadalah cara untuk pergi, namun banyak kernel (termasuk Linux) hanya menerima argumen tunggal ke program shebang.

Jika tidak, Anda bisa membuat program polyglot yang merupakan pembungkus shell dan skrip awk. Ini satu untuk awk.

#!/bin/sh
true + /; exec gawk -f "$0"; exit; / {}
# awk script starts here

Penguraian shell:

  • true + /;- perintah true(yang tidak melakukan apa-apa) dengan dua argumen inert +dan /.
  • Panggilan ke gawk. Ini bisa berupa cuplikan shell yang tidak mengandung baris baru dan di mana garis miring ditulis \/(shell tidak keberatan kecuali di dalam tanda kutip).
    Panggilan digunakan execuntuk mengganti shell dengan gawk alih-alih mengeksekusi gawk sebagai subproses.
  • exit;- keluar dari shell, seandainya gawk tidak ditemukan. Apa pun setelah itu diabaikan, kecuali bahwa itu harus sintaks shell yang valid jika shell mencoba untuk menguraikan seluruh baris sebelum mulai menjalankannya.

Penguraian awk:

  • Bit antara garis miring adalah ekspresi reguler.
  • true + /REGEX/- sebuah kondisi. trueadalah variabel yang tidak terdefinisi sehingga nilai numeriknya adalah 0, tidak penting.
  • {} - Jika kondisi tersebut berlaku, jangan lakukan apa pun.
Gilles 'SANGAT berhenti menjadi jahat'
sumber
5

Solusi yang diusulkan Gilles memang merupakan pendekatan yang sangat baik (akhirnya memiliki reputasi untuk memilih dalam jabatannya :)).

Bagaimanapun, sejauh yang saya mengerti execperintah, itu membuat exithak setelah itu tidak perlu, sebenarnya tidak dapat dijangkau, karena proses shell diganti oleh awk.

Selain itu, untuk memungkinkan awkskrip mengakses parameter doa, saya akan menyarankan beberapa perubahan dalam solusi yang diusulkan:

#!/bin/sh
true + /; exec -a "$0" gawk -f "$0" -- "$@"; / {}
# awk script starts here

The -a "$0"memungkinkan script untuk memiliki akses ke nama doa nya, selain itu akan selalu mendapatkan awkatau gawkketika mengakses ARGV[0]variabel. Demikian pula, "$@"memungkinkan skrip untuk mengakses parameter yang tersisa dalam ARGV[1...N]array dan --sebelumnya memungkinkan skrip untuk menerima -<something>argumen tanpa gawk menafsirkannya dimaksudkan untuk itu.

Satu hal yang perlu diingat / dipertimbangkan adalah menambahkan exit(0);pernyataan di akhir BEGIN { ... }blok awkprogram skrip, jika tidak awkakan mengancam semua parameter yang diteruskan ke skrip sebagai file input. (Harap dicatat bahwa itu tidak ada hubungannya, sama sekali, dengan exitpernyataan yang kami hapus dari true + ...baris, ini adalah pernyataan shell yang tidak dapat dijangkau saat keluar yang disarankan ini ada dalam kode awk).

Marcelo
sumber
Itu exit(0)sangat berguna! Juga, untuk pengguna macos, lihat intisari ini: Shebang portabel yang bagus tidak mudah ditemukan.
Seamus