¿Por qué sed me da un error sobre una 's' sin terminar?

9

Tengo un conjunto de reemplazos sed en un script bash y recibo un error sobre un comando 's' no terminado. Así es como se ve la línea 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

Sin embargo, por alguna razón, a bash no le gusta esto y recibo un error sobre

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

¿Que me estoy perdiendo aqui? ¿Cómo puedo hacer que SED ingrese la variable? Me parece que todos están terminados.

Mike B
fuente
2
$ FOO4 contiene algo extraño (por ejemplo, "\" o "\\"?) Que hace que el comando sed s no finalice. (Es por eso que creo que es una "\" final, haciendo que la siguiente "/" sea tratada como un carácter parte de la cadena de reemplazo, en lugar de como el carácter final para el comando s)
Olivier Dulac

Respuestas:

7

No puede interpolar una variable de forma segura en un comando sed, porque la sustitución se realiza por el shell, no por sed. El valor de la variable se convierte en sintaxis sed. Por ejemplo, en "s/TMPFOO1/$FOO1/", si $FOO1contiene una nueva línea, esto causará un error de sintaxis como el que observó. Si $FOO1contiene un /, esto termina el scomando y puede causar un error o puede hacer que se ejecuten otros comandos (si lo que /sucede después de la sintaxis sed es válida).

Si bien puede hacer un primer paso de sustitución FOO1para citar sus caracteres especiales para su inclusión en ese comando sed, es mucho más simple usar awk. Awk tiene una noción de variable y una sintaxis de línea de comando para establecer el valor inicial de una variable.

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- deja de ser malvado'
fuente
Nota trivial: - a -vdebe preceder a cada declaración de variable.
Mike B
@ MikeB Gracias por el informe de error. En general, edite la publicación directamente cuando encuentre errores tipográficos como este.
Gilles 'SO- deja de ser malvado'
@Gilles Las ediciones de no autores deben tener al menos seis caracteres.
NobleUplift
6

Lo más probable es que una de sus $FOOvariables contenga caracteres especiales interpretados por sed.

Tengo otra versión de la sedcual genera otros mensajes de error, pero aquí hay un ejemplo de un problema similar:

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

En este caso $VARcontiene un carácter que se interpreta sedcomo la barra diagonal final.

Matteo
fuente
2

Como otros han mencionado aquí, depende del contenido de sus variables FOO *. En su caso, usar sedes la elección incorrecta porque probablemente contenga algunos caracteres especiales.

Eche un vistazo a este enlace y vea la funcióngsub_literal

Como gsub_literallee de stdin y escribe en stdout, el uso será:

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

Salida de muestra:

rany$ cat > foo.txt
a'
a'

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

El problema se ha resuelto para mí probando barras diagonales adicionales dentro del sed 's/.../.../g'comando. Este comando

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

me dio este mensaje de error

sed: -e expresión # 1, char 9: comando 's' sin terminar

cuando se ejecutó como parte de un script c-shell, y lo hizo solo con una versión reciente de sed, no con una versión anterior. (Curiosamente, el mismo comando funciona bien cuando se da en la línea de comando (en un shell tc)).

El problema con el script c-shell se ha solucionado precediendo al äcarácter con una barra diagonal inversa:

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