web-dev-qa-db-ja.com

sedが終了していない `s 'に関するエラーを表示するのはなぜですか?

Bashスクリプトに一連のsed置換があり、終了していない「s」コマンドに関するエラーが発生します。 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

しかし、何らかの理由で、bashはこれを好みません。

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

ここで何が欠けていますか? SEDに変数を入力させるにはどうすればよいですか?それらはすべて終了しているように見えます。

9
Mike B

置換はsedではなくシェルによって実行されるため、sedコマンドで変数を安全に補間することはできません。変数の値はsed構文になります。たとえば、"s/TMPFOO1/$FOO1/"では、$FOO1に改行が含まれていると、観察したような構文エラーが発生します。 $FOO1/が含まれている場合、これによりsコマンドが終了し、エラーが発生したり、他のコマンドが実行されたりする可能性があります(/の後にあるものが有効なsed構文)。

FOO1の最初の置換を行って特殊文字を引用し、そのsedコマンドに含めることができますが、awkを使用する方がはるかに簡単です。 Awkには変数の概念と、変数の初期値を設定するコマンドライン構文があります。

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

おそらくあなたの$FOO変数には、sedによって解釈される特殊文字が含まれています。

他のエラーメッセージを生成するsedの別のバージョンがありますが、同様の問題の例を次に示します。

$ 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: '/'

この場合 $VARには、sedによって末尾のスラッシュとして解釈される文字が含まれています。

6
Matteo

他の人がここで述べたように、それはあなたのFOO *変数の内容に依存します。あなたの場合、おそらくいくつかの特殊文字が含まれているため、sedの使用は間違った選択です。

このリンク を見て、関数gsub_literalを見てください。

gsub_literalはstdinから読み取り、stdoutに書き込むため、使用法は次のようになります。

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

出力例:

rany$ cat > foo.txt
a'
a'

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

この問題は、sed 's/.../.../g'コマンド内で追加のバックスラッシュを試すことで解決されました。このコマンド

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

このエラーメッセージが表示されました

sed:-e expression#1、char 9:終了していない `s 'コマンド

c-Shellスクリプトの一部として実行されたとき、それはsedの最近のバージョンでのみ実行され、古いバージョンでは実行されませんでした。 (奇妙なことに、同じコマンドがコマンドラインで(tc-Shellで)指定された場合は正常に機能します)。

C-Shellスクリプトの問題は、ä文字の前にバックスラッシュを付けることで修正されています。

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