2012-04-25 12 views
21

Non riesco a capire come utilizzare sed per cercare e sostituire stringhe contenenti il ​​carattere / in un file di testo /etc/myconfig.sed cerca e sostituisce stringhe contenenti/

Per esempio, nel mio file di testo esistente, ho:

myparam /path/to/a argB=/path/to/B xo 

e voglio che questo sostituito dal seguente:

myparam /path/to/c argB=/path/to/D xo 

Ho tentato di fare questo in bash:

line='myparam /path/to/a argB=/path/to/B xo' 
line_new='myparam /path/to/c argB=/path/to/D xo' 
sed -i 's/$line/$line_new/g' /etc/myconfig 

Ma non succede nulla.

Cercando

grep -rn "$line" /etc/myconfig 

mi fa tornare 'myparam /path/to/a argB=/path/to/B xo' però.

Qual è il modo corretto di esprimere il mio comando sed per eseguire questa ricerca e sostituire e gestire correttamente il comando /? (Mi sa che il personaggio / nelle mie corde sono quelli mi dà il problema perché ho usato un simile sed comando per cercare e sostituire un'altra riga nel file di testo senza problemi e che la linea non ha un carattere /.

+1

Le regole di sostituzione e quotazione riguardano in realtà bash piuttosto che sed in particolare. Potresti voler aggiungere bash come tag. – KarlM

+0

ok. aggiungerà 'bash' come tag. –

risposta

32

non sfuggono le barre inverse, ne avrete confondere te stesso Utilizzare un simbolo diverso dopo il comando s che non appare nel testo (sto usando % nell'esempio qui sotto):

line_old='myparam /path/to/a argB=/path/to/B xo' 
line_new='myparam /path/to/c argB=/path/to/D xo' 
sed -i "s%$line_old%$line_new%g" /etc/myconfig 

anche. , racchiudi l'intera stringa tra virgolette doppie, utilizzando virgolette singole significa che sed vede $line (nell'originale) anziché il valore espanso. All'interno delle virgolette singole, non c'è espansione e non ci sono metacaratteri. Se il testo può contenere quasi tutti i caratteri di testo normale, utilizzare un carattere di controllo (ad esempio control-A o control-G) come delimitatore.

Si noti che l'uso di -i qui rispecchia ciò che è nella domanda, ma che presuppone l'uso di GNU sed. BSD sed (disponibile anche su Mac OS X) richiede un suffisso. È possibile utilizzare sed -i '' … per sostituire in situ; non funziona con GNU sed. Per essere portatili tra i due, utilizzare -i.bak; che funzionerà con entrambi, ma ti fornirà un file di backup che probabilmente vorrai eliminare. Altre piattaforme Unix (ad esempio AIX, HP-UX, Solaris) potrebbero avere varianti di sed che non supportano affatto lo -i. Non è richiesto dalle specifiche POSIX per sed.

+0

grazie!La doppia citazione '" 'e'% 'ha fatto il trucco. Inizialmente ho provato a sfuggire al carattere'/'facendo' \/'e non funzionava affatto. –

+0

Nota che se devi specificare un intervallo di linee per regex e la regex contiene le barre, puoi usare 'sed -n '\ @ dir/file @, \ @ dir2/file2 @ p' dove il backslash prima di' @ 'indica che' @ 'è il delimitatore di ricerca per questa espressione –

+0

Nota che potrebbe essere necessario 'sed -i -e' – PhysicalChemist

12

Questo potrebbe funzionare per voi:

sed -i "s|$line|$line_new|g" /etc/myconfig 

è necessario utilizzare " 's in modo che il $line e $new_line sono interpolati. Utilizzare anche | o qualsiasi carattere non trovato nelle corrispondenze o nelle stringhe di sostituzione come delimitatore.

+1

ok. Non sapevo del trucco '|' Quindi intendi dire che QUALSIASI delimitatore funzionerà finché non sarà trovato un carattere nella ricerca o sostituire le stringhe? –

+0

Sì; il primo carattere dopo il 's' viene usato per separare il comando in due parti; il modello da abbinare e il modello di sostituzione. 's/cerca/sostituisci /' usa '/' tre volte; ma 's | search | replace |' or 's% search% replace%' funziona anche. Perl consente parentesi di corrispondenza ('s {search} {replace}') ma 'sed' no (a meno che, forse, non sia stata attivata l'opzione Perl patterns se si ha GNU' sed'). –

+1

Sì, entro limiti ragionevoli. '|' è una pratica da usare in quanto non è probabile che appaia in un file. Comunque è un metacarattere (usato in alternanza) quindi se vuoi dire 's/this \ | that/those /' usa un altro delimitatore come '@' o '#' o ',' o '?' Or ' % 'ecc. Si noti anche che questo è per il comando di sostituzione per il comando di ricerca' /.../ 'per usare un delimitatore alternativo precedere l'alternativa con un backslash ad es. '\ | foo |' – potong

Problemi correlati