Почему sed дает мне ошибку о неопределенном `s '?

9

У меня есть набор замен sed в скрипте bash, и я получаю сообщение об ошибке о неопределенной команде `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 ввести переменную? Мне кажется, что все они уничтожены.

Майк Б
источник
2
$ FOO4 содержит что-то странное (например, "\" или "\\"?), Которое делает команду sed s не завершенной. (Вот почему я думаю, что это завершающий символ "\", заставляющий следующий "/" обрабатываться как символьная часть строки замены, а не как завершающий символ для команды s)
Оливье Дюлак

Ответы:

7

Вы не можете безопасно интерполировать переменную в команде sed, потому что подстановка выполняется оболочкой, а не sed. Значение переменной становится синтаксисом sed. Например, "s/TMPFOO1/$FOO1/"если $FOO1в строке содержится символ новой строки, это приведет к синтаксической ошибке, подобной той, которую вы наблюдали. Если $FOO1содержит a /, это завершает 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
Жиль "ТАК - перестань быть злым"
источник
Тривиальное примечание: - a -vдолжен предшествовать каждому объявлению переменной.
Майк Б
@MikeB Спасибо за сообщение об ошибке. В общем, пожалуйста, отредактируйте сообщение напрямую, когда найдете опечатки, подобные этой
Жиль "ТАК ... перестать быть злым"
@ Жиль Редактирование от не-авторов должно быть не менее шести символов.
NobleUplift
6

Скорее всего, одна из ваших $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как завершающий слеш.

Matteo
источник
2

Как уже упоминали другие, это зависит от содержимого ваших переменных 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
Рани Албег Вайн
источник
1

Проблема была решена для меня путем пробной обратной косой черты в sed 's/.../.../g'команде. Эта команда

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

дал мне это сообщение об ошибке

sed: -e выражение # 1, char 9: неопределенная команда `s '

когда он был выполнен как часть скрипта c-shell, и он делал это только с последней версией sed, а не со старой версией. (Странно, эта же команда отлично работает, когда она дается в командной строке (в tc-shell)).

Проблема со сценарием c-shell была исправлена ​​путем добавления äсимвола обратной косой черты:

sed 's/\"a/\ä/g' input_file
user3346151
источник