Perché sed mi sta dando un errore su una `s 'non terminata?


9

Ho una serie di sostituzioni sed in uno script bash e sto ricevendo un errore su un comando `s 'non terminato. Ecco come appare la linea 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

Per qualche ragione, a bash non piace questo e ricevo un errore

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

Cosa mi sto perdendo qui? Come posso inserire SED nella variabile? Mi sembra che siano tutti chiusi.


2
$ FOO4 contiene qualcosa di strano (es: "\" o "\\"?) Che rende il comando sed s non terminato. (Ecco perché penso che sia un "\" finale, facendo in modo che il prossimo "/" sia trattato come parte del carattere della stringa di sostituzione, anziché come carattere finale per il comando s)
Olivier Dulac,

Risposte:


7

Non è possibile interpolare in modo sicuro una variabile in un comando sed, poiché la sostituzione viene eseguita dalla shell, non da sed. Il valore della variabile diventa sintassi sed. Ad esempio, in "s/TMPFOO1/$FOO1/", se $FOO1contiene una nuova riga, ciò causerà un errore di sintassi come quello che hai osservato. Se $FOO1contiene a /, questo termina il scomando e può causare un errore o può causare l'esecuzione di altri comandi (se ciò che /accade dopo è la sintassi sed valida).

Mentre puoi fare un primo passaggio di sostituzione FOO1per citare i suoi caratteri speciali per l'inclusione in quel comando sed, è molto più semplice usare awk. Awk ha una nozione di variabile e una sintassi della riga di comando per impostare il valore iniziale di una variabile.

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

Nota fondamentale: - a -vdeve precedere ogni dichiarazione di variabile.
Mike B,

@MikeB Grazie per la segnalazione di bug. In generale, modifica il post direttamente quando trovi errori di battitura in questo modo.
Gilles 'SO- smetti di essere malvagio' il

@Gilles Le modifiche da non autori devono essere di almeno sei caratteri.
NobleUplift,

6

Molto probabilmente una delle tue $FOOvariabili contiene caratteri speciali interpretati da sed.

Ho un'altra versione di sedcui genera altri messaggi di errore, ma qui è un esempio di un problema simile:

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

In questo caso $VARcontiene un personaggio che viene interpretato sedcome una barra finale.


2

Come altri hanno già detto qui, dipende dal contenuto delle variabili FOO *. Nel tuo caso, usare sedè la scelta sbagliata perché probabilmente contiene alcuni caratteri speciali.

Dai un'occhiata a questo link e vedi la funzionegsub_literal

Poiché gsub_literallegge da stdin e scrive su stdout, l'utilizzo sarà:

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

Uscita campione:

rany$ cat > foo.txt
a'
a'

rany$ gsub_literal a\' b < foo.txt 
b
b

1

Il problema è stato risolto per me provando ulteriori barre rovesciate all'interno del sed 's/.../.../g'comando. Questo comando

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

mi ha dato questo messaggio di errore

sed: -e espressione # 1, carattere 9: comando `s 'non terminato

quando è stato eseguito come parte di uno script c-shell, e lo ha fatto solo con una versione recente di sed, non con una versione precedente. (Stranamente, lo stesso comando funziona bene quando viene dato sulla riga di comando (in una shell tc)).

Il problema con lo script c-shell è stato risolto precedendo il äcarattere da una barra rovesciata:

sed 's/\"a/\ä/g' input_file
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.