Mengetik /usr/bin/env sed -f
dalam pekerjaan terminal.
Tetapi jika menggunakannya sebagai shebang,
#!/usr/bin/env sed -f
s/a/b/
Script akan gagal dieksekusi:
/usr/bin/env: sed -f: No such file or directory
Saya agak percaya bahwa itu terkait dengan -f. Tetapi bagaimana cara mengatasinya?
scripting
sed
executable
env
Cheng
sumber
sumber
Jawaban:
Anda tidak bisa, dengan mudah, menempatkan lebih dari satu argumen pada satu
#!
baris . Itu berarti hanya path lengkap dan satu argumen (mis#!/bin/sed -f
atau#!/usr/bin/sed -f
), atau#!/usr/bin/env
dan tidak ada argumen untuk penerjemah.Sebuah solusi untuk mendapatkan skrip portabel adalah dengan menggunakan
#!/bin/sh
dan pembungkus shell, melewati skrip sed sebagai argumen baris perintah. Perhatikan bahwa ini tidak disetujui oleh POSIX (skrip multi-instruksi harus ditulis dengan-e
argumen terpisah untuk setiap instruksi untuk portabilitas), tetapi ia bekerja dengan banyak implementasi.Untuk skrip yang panjang, mungkin lebih nyaman menggunakan heredoc. Keuntungan dari heredoc adalah bahwa Anda tidak perlu mengutip kutipan tunggal di dalam, jika ada. Kelemahan utama adalah bahwa skrip diumpankan ke input standarnya, dengan dua konsekuensi yang mengganggu. Beberapa versi sed membutuhkan
-f /dev/stdin
bukan-f -
, yang merupakan masalah untuk portabilitas. Lebih buruk lagi, skrip tidak dapat bertindak sebagai filter, karena input standar adalah skrip dan tidak dapat berupa data.Kelemahan dari heredoc dapat diatasi dengan penggunaan yang bermanfaat
cat
. Karena ini menempatkan seluruh skrip pada baris perintah lagi, itu bukan POSIX-compliant, tetapi sebagian besar portabel dalam praktek.Solusi lain adalah dengan menulis skrip yang dapat diuraikan baik oleh sh dan oleh sed. Ini portabel, cukup efisien, hanya sedikit jelek.
Penjelasan:
b
; isinya tidak masalah asalkan fungsi tersebut terbentuk dengan baik secara sintaksis (khususnya, Anda tidak dapat memiliki fungsi kosong). Kemudian jika benar (yaitu selalu), jalankansed
pada script.()
label, kemudian beberapa input yang terbentuk dengan baik. Lalu sebuahi
perintah, yang tidak memiliki efek karena selalu dilewati. Akhirnya()
label diikuti oleh bagian skrip yang bermanfaat.sumber
#!/usr/bin/env
dan tidak ada argumen." tidak diungkapkan dengan sangat baik. Mungkin "atau#!/usr/bin/env sed
dan tidak ada argumen untuk sed."Ada berbagai implementasi yang tidak kompatibel dari shebang (#!) Tergantung pada OS. Ada yang membangun daftar argumen lengkap, ada yang mempertahankan jalur perintah dan menempatkan semua argumen yang tersisa sebagai satu, ada yang mengabaikan semua argumen dan hanya melewati jalur perintah, dan akhirnya, beberapa melewati seluruh string sebagai satu perintah. Anda tampaknya berada dalam kasus terakhir.
sumber
env sedang mencoba menemukan file dengan nama "sed -f". Anda dapat mencoba "#! / Usr / bin / sed -f" sebagai baris shebang Anda.
sumber
Pada GNU coreutils v8.30 , Anda dapat melakukan:
Fitur ini telah ditambahkan dalam baru-baru ini (2018/04/20) berkomitmen untuk
env.c
di GNU coreutils paket, yang menambahkan-S
atau--split-string
pilihan.Dari
env
halaman manual:Lebih banyak contoh tersedia di manual GNU coreutils .
Jika Anda juga menggunakan
-v
opsi untuk keluaran verbose, Anda dapat melihat dengan tepat bagaimana caraenv
membagi string argumen:Dalam
my_sed_script.sed
:Eksekusi:
Catatan: Ini hanya berlaku untuk shebang yang menggunakan
/usr/bin/env
, seperti--split-string
juga fitur GNUenv
.sumber
Jawaban ini memberikan jalan ke solusi yang elegan: /programming//a/1655389/642372
read
a heredoc menjadi variabel shell.sed
.Mencicipi:
sumber
Saya suka solusi Walker, tetapi bisa diperbaiki (meletakkan ini di jawaban yang terpisah karena komentar tidak menerima teks yang telah diformat sebelumnya). Ini mungkin tidak berfungsi pada semua versi Linux atau Bash, tetapi pada Ubuntu 17.10 Anda dapat memotong ini sebagai berikut:
Anda dapat menghapus
eval
dan menyederhanakanread
perintah, tetapi Anda harus menyingkirkan komentar di dalam heredoc.Juga, untuk semua yang ingin Anda ketahui tentang sed tetapi takut untuk bertanya, ada tutorial yang sangat berguna di http://www.grymoire.com/unix/sed.html . Ini menyarankan solusi yang lebih baik, dengan mengorbankan kehilangan
/usr/bin/env
dan mengkodekan jalur ke sed:Ini memiliki keuntungan tambahan untuk mendukung lebih dari satu
s///
penggantian.sumber