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

8

Eu tenho um conjunto de substituições de sed em um script bash e estou recebendo um erro sobre um comando 'não terminado'. Veja como é a 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 algum motivo, o bash não gosta disso e eu recebo um erro sobre

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

O que estou perdendo aqui? Como posso ter SED inserindo a variável? Parece-me que estão todos terminados.

    
por Mike B 10.05.2013 / 07:05

4 respostas

4

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

Enquanto você pode fazer uma primeira passagem de substituição de FOO1 para citar seus caracteres especiais para inclusão nesse comando sed, é muito mais simples usar o awk. O awk tem 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
    
por 13.05.2013 / 03:21
6

O mais provável é que uma das suas variáveis $FOO contenha caracteres especiais que são interpretados por sed .

Eu tenho outra versão do sed que 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, $VAR contém um caractere que é interpretado por sed como a barra final.

    
por 10.05.2013 / 07:16
2

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

Dê uma olhada no este link e veja a função gsub_literal

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

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

Exemplo de saída:

rany$ cat > foo.txt
a'
a'

rany$ gsub_literal a\' b < foo.txt 
b
b
    
por 10.05.2013 / 21:05
1

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

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

me deu essa mensagem de erro

sed: -e expression #1, char 9: unterminated 's' command

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

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

sed 's/\"a/\ä/g' input_file
    
por 03.08.2014 / 12:45