Почему sed дает мне ошибку в отношении неиспользуемого `s '?

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

Вы не можете безопасно интерполировать переменную в команде sed, потому что подстановка выполняется оболочкой, а не sed. Значение переменной становится синтаксисом sed. Например, в "s/TMPFOO1/$FOO1/" , если $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 как конечная косая черта.

Как упоминалось выше, это зависит от содержания ваших переменных 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 

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

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

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

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

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

Проблема с скриптом c-shell была устранена, если предыдущий символ «a» был обратным:

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