Mengapa saya memberi saya kesalahan tentang `s 'yang tidak ditentukan?

9

Saya memiliki satu set pengganti sed dalam skrip bash dan saya mendapatkan kesalahan tentang perintah `s 'yang tidak ditakdirkan. Inilah yang terlihat seperti garis sed:

sed -n -e "s/TMPFOO1/$FOO1/" -e "s/TMPFOO2/$FOO2/" -e "s/TMPFOO3/$FOO3/" -e "s/TMPFOO4/$FOO4/" -e "s/TMPFOO5/$FOO5/" /home/foo/template > /home/foo/template/finishedresult

Untuk beberapa alasan, bash tidak suka ini dan saya mendapatkan kesalahan

sed: -e expression #4, char 69: unterminated `s' command

Apa yang kulewatkan di sini? Bagaimana saya bisa meminta SED memasukkan variabel? Bagi saya sepertinya mereka semua dihentikan.

Mike B
sumber
2
$ FOO4 berisi sesuatu yang aneh (mis: "\" atau "\\"?) Yang membuat perintah sed tidak dihentikan. (Itu sebabnya saya pikir itu "" "tertinggal, membuat" / "berikutnya diperlakukan sebagai bagian karakter dari string pengganti, bukan sebagai karakter terminating untuk perintah s)
Olivier Dulac

Jawaban:

7

Anda tidak dapat dengan aman menginterpolasi variabel dalam perintah sed, karena penggantian dilakukan oleh shell, bukan oleh sed. Nilai variabel menjadi sintaks sed. Misalnya, dalam "s/TMPFOO1/$FOO1/", jika $FOO1berisi baris baru, ini akan menyebabkan kesalahan sintaksis seperti yang Anda amati. Jika $FOO1mengandung a /, ini mengakhiri sperintah dan dapat menyebabkan kesalahan atau dapat menyebabkan perintah lain dieksekusi (jika apa yang /terjadi setelahnya adalah sintaks sed yang valid).

Meskipun Anda dapat melakukan langkah pertama untuk menggantikan FOO1karakter khusus untuk dimasukkan dalam perintah sed, itu jauh lebih mudah untuk menggunakan awk. Awk memiliki gagasan tentang variabel, dan sintaks baris perintah untuk mengatur nilai awal suatu variabel.

awk -v FOO1="$FOO1" -v FOO2="$FOO2" -v FOO3="$FOO3" -v FOO4="$FOO4" -v FOO5="$FOO5" '{
    sub(/TMPFOO1/, FOO1);
    sub(/TMPFOO2/, FOO2);
    sub(/TMPFOO3/, FOO3);
    sub(/TMPFOO4/, FOO4);
    sub(/TMPFOO5/, FOO5);
    print;
}' /home/foo/template > /home/foo/template/finishedresult
Gilles 'SANGAT berhenti menjadi jahat'
sumber
Catatan sepele: - -vkebutuhan untuk mendahului setiap deklarasi variabel.
Mike B
@MikeB Terima kasih atas laporan bugnya. Secara umum, silakan edit posting secara langsung ketika Anda menemukan kesalahan ketik seperti ini.
Gilles 'SO- stop being evil'
@Gilles Edits dari bukan penulis harus terdiri dari setidaknya enam karakter.
NobleUplift
6

Kemungkinan besar salah satu $FOOvariabel Anda berisi karakter khusus yang ditafsirkan oleh sed.

Saya memiliki versi lain sedyang menghasilkan pesan kesalahan lain tetapi di sini adalah contoh dari masalah yang sama:

$ VAR=a
$ echo i | sed -e "s/i/"$VAR"/"
a
$ tmp> VAR=/
$ echo i | sed -e "s/i/"$VAR"/"
sed: 1: "s/i///
": bad flag in substitute command: '/'

Dalam hal ini $VARberisi karakter yang ditafsirkan sedsebagai garis miring.

Matteo
sumber
2

Seperti yang disebutkan orang lain di sini, itu tergantung pada konten variabel FOO * Anda. Dalam kasus Anda, menggunakan sedadalah pilihan yang salah karena mungkin mengandung beberapa karakter khusus.

Lihatlah tautan ini dan lihat fungsinyagsub_literal

Sejak gsub_literalmembaca dari stdin dan menulis ke stdout, penggunaannya akan:

gsub_literal "$search" "$replace" < /home/foo/template > /home/foo/template/finishedresult

Output sampel:

rany$ cat > foo.txt
a'
a'

rany$ gsub_literal a\' b < foo.txt 
b
b
Rany Albeg Wein
sumber
1

Masalahnya telah diatasi untuk saya dengan mencoba backslash tambahan dalam sed 's/.../.../g'perintah. Perintah ini

sed 's/\"a/ä/g' input_file

memberi saya pesan kesalahan ini

sed: -e ekspresi # 1, char 9: perintah `s 'yang tidak dikalahkan

ketika dieksekusi sebagai bagian dari skrip c-shell, dan ia melakukannya hanya dengan versi terbaru sed, bukan dengan versi yang lebih lama. (Anehnya, perintah yang sama berfungsi dengan baik ketika diberikan pada baris perintah (dalam shell-tc)).

Masalah dengan skrip c-shell telah diatasi dengan mendahului äkarakter dengan backslash:

sed 's/\"a/\ä/g' input_file
pengguna3346151
sumber