Por que o sed está me dando um erro sobre um `s 'não terminado?

9

Eu tenho um conjunto de substituições sed em um script bash e estou recebendo um erro sobre um comando `s 'não terminado. Aqui está a aparência da linha 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

Por alguma razão, o bash não gosta disso e recebo um erro sobre

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

O que estou perdendo aqui? Como posso o SED inserir a variável? Parece-me que todos eles foram encerrados.

Mike B
fonte
2
$ FOO4 contém algo estranho (ex: "\" ou "\\"?) Que faz com que o comando sed s não seja encerrado. (É por isso que eu acho que é um "\" à direita, fazendo com que o próximo "/" seja tratado como parte do caractere da cadeia de substituição, em vez de como o caractere final do comando s)
Olivier Dulac

Respostas:

7

Você não pode interpolar com segurança uma variável em um comando sed, porque a substituição é realizada pelo shell, não pelo sed. O valor da variável se torna a sintaxe sed. Por exemplo, em "s/TMPFOO1/$FOO1/", se $FOO1contiver uma nova linha, isso causará um erro de sintaxe como o que você observou. Se $FOO1contiver a /, isso encerrará o scomando e poderá causar um erro ou executar outros comandos (se o que se /segue a seguir for uma sintaxe sed válida).

Embora você possa fazer uma primeira substituição FOO1para citar seus caracteres especiais para inclusão nesse comando sed, é muito mais simples usar o awk. O Awk possui uma noção de variável e uma sintaxe de linha de comando para definir o valor inicial de uma variável.

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 'SO- parar de ser mau'
fonte
Nota trivial: - a -vprecisa preceder cada declaração de variável.
Mike B
@ MikeB Obrigado pelo relatório de erros. Em geral, edite a postagem diretamente quando encontrar erros de digitação como este.
Gilles 'SO- stop be evil'
As edições do @Gilles de não autores devem ter pelo menos seis caracteres.
NobleUplift
6

Provavelmente uma de suas $FOOvariáveis ​​contém caracteres especiais que são interpretados por sed.

Eu tenho outra versão do sedqual gera outras mensagens de erro, mas aqui está um exemplo de um problema semelhante:

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

Nesse caso, $VARcontém um caractere que é interpretado sedcomo a barra final.

Matteo
fonte
2

Como outros já mencionaram aqui, isso depende do conteúdo de suas variáveis ​​FOO *. No seu caso, usar sedé a escolha errada, pois provavelmente contém alguns caracteres especiais.

Dê uma olhada neste link e veja a funçãogsub_literal

Como gsub_literallê stdin e grava em stdout, o uso será:

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

Saída de amostra:

rany$ cat > foo.txt
a'
a'

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

O problema foi resolvido para mim ao tentar barras invertidas adicionais dentro do sed 's/.../.../g'comando. Este comando

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

me deu essa mensagem de erro

expressão sed: -e # 1, caractere 9: comando `s 'não terminado

quando foi executado como parte de um script c-shell, e somente com uma versão recente de sed, não com uma versão mais antiga. (Estranhamente, o mesmo comando funciona bem quando é fornecido na linha de comando (em um shell tc)).

O problema com o script c-shell foi corrigido precedendo o äcaractere por uma barra invertida:

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