Risposte:
Utilizza un delimitatore regex alternativo che sedti consente di utilizzare qualsiasi delimitatore ( inclusi i caratteri di controllo ):
sed "s~$var~replace~g" $file
$var
Una risposta bash pura: usa l' espansione dei parametri per eseguire l'escape della barra rovesciata da qualsiasi barra nella variabile:
var="/Users/Documents/name/file"
sed "s/${var//\//\\/}/replace/g" $file
${parameter/pattern/string}. Quindi, in questo caso, il parametro è var, il modello è /\/e la stringa è \\/. Tutte le istanze del modello vengono sostituite perché il modello inizia con a /.
Usare /in sed come delimitatore entrerà in conflitto con le barre nella variabile quando sostituite e di conseguenza otterrai un errore. Un modo per aggirare questo problema consiste nell'usare un altro delimitatore univoco rispetto a qualsiasi carattere presente in quella variabile.
var="/Users/Documents/name/file"
puoi usare il personaggio octothorpe che si adatta all'occasione (o qualsiasi altro personaggio che non sia /per facilità d'uso)
sed "s#$var#replace#g"
o
sed 's#$'$var'#replace#g'
questo è adatto quando la variabile non contiene spazi
o
sed 's#$"'$var'"#replace#g'
È più saggio usare quanto sopra visto che siamo interessati a sostituire qualunque cosa sia in quella variabile solo rispetto alla doppia citazione dell'intero comando che può far sì che la tua shell interpreti qualsiasi carattere che potrebbe essere considerato un carattere di shell speciale nella shell.
$varcontiene ~, dovrai ovviamente scegliere un delimitatore diverso. L'errore "non terminato" sembra che il tuo $varcontenga una nuova riga; potresti essere in grado di risolverlo facendo l'escape di backslash ogni nuova riga nel valore, ma non penso che sia completamente portabile. Questo è in linea di massima estraneo al problema delle barre nel valore.
sed -i "s~blah~$var~g" filecon virgolette solo intorno allo sedscript attuale .
Questa è una vecchia domanda, ma nessuna delle risposte qui discute le operazioni se non s/from/to/in modo molto dettagliato.
La forma generale di una seddichiarazione è
*address* *action*
dove indirizzo può essere un intervallo regex o un intervallo di numeri di riga (o vuoto, nel qual caso l' azione viene applicata a ogni riga di input). Quindi per esempio
sed '1,4d' file
cancellerà le righe da 1 a 4 (l' indirizzo è l'intervallo di numeri di riga 1,4e l' azione è il dcomando di eliminazione); e
sed '/ick/,$s/foo/bar/' file
sostituirà la prima occorrenza di foocon barsu qualsiasi riga tra la prima corrispondenza della regex icke la fine del file (l' indirizzo è l'intervallo /ick/,$e l' azione è il scomando sostitutivo s/foo/bar/).
In questo contesto, se ickprovenisse da una variabile, si potrebbe fare
sed "/$variable/,\$s/foo/bar/"
(si noti l'uso di virgolette doppie anziché singole, in modo che la shell possa interpolare la variabile e la necessità di citare il segno letterale del dollaro tra virgolette doppie) ma se la variabile contiene una barra, si otterrà un errore di sintassi. (La shell espande la variabile, quindi passa la stringa risultante a sed; quindi sedvede solo il testo letterale - non ha il concetto delle variabili della shell.)
La cura è usare un diverso delimitatore (dove ovviamente devi poter usare un carattere che non può comparire nel valore della variabile), ma a differenza del s%foo%bar%caso, hai anche bisogno di una barra rovesciata prima del delimitatore se vuoi usare un diverso delimitatore rispetto a quello predefinito /:
sed "\\%$variable%,\$s/foo/bar/" file
(all'interno di virgolette singole, una singola barra rovesciata sarebbe ovviamente sufficiente); oppure puoi sfuggire separatamente a ogni barra nel valore. Questa particolare sintassi è solo Bash:
sed "/${variable//\//\\/}/,\$s/foo/bar/" file
o se usi una shell diversa, prova
escaped=$(echo "$variable" | sed 's%/%\\/%g')
sed "s/$escaped/,\$s/foo/bar/" file
Per chiarezza, se $variablecontenesse la stringa, 1/2i comandi precedenti sarebbero equivalenti a
sed '\%1/2%,$s/foo/bar/' file
nel primo caso, e
sed '/1\/2/,$s/foo/bar/' file
nel secondo.
Usa Perl, dove le variabili sono cittadini di prima classe, non solo macro in espansione:
var=/Users/Documents/name/file perl -pe 's/\Q$ENV{var}/replace/g' $file
-p legge l'input riga per riga e stampa la riga dopo l'elaborazione\Qcita tutti i metacaratteri nella seguente stringa (non necessario per il valore presentato qui, ma necessario se il valore contenuto [o altri valori speciali per espressioni regolari)