Come sostituire le stringhe contenenti barre con sed?


147

Ho un progetto Visual Studio, che è sviluppato localmente. I file di codice devono essere distribuiti su un server remoto. L'unico problema è che URLsthey contiene quali sono codificati.

Il progetto contiene URL come ? Page = one . Perché il collegamento sia valido sul server, deve essere / page / one .

Ho deciso di sostituire tutti gli URL nei miei file di codice con sed prima della distribuzione, ma sono bloccato su barre.

So che questa non è una soluzione carina, ma è semplice mi farebbe risparmiare un sacco di tempo. Il numero totale di stringhe che devo sostituire è inferiore a 10. Il numero totale di file che devono essere controllati è ~ 30.

L'esempio che descrive la mia situazione è di seguito:

Comando che sto usando:

sed -f replace.txt < a.txt > b.txt

replace.txt che contiene tutte le stringhe:

s/?page=one&/pageone/g
s/?page=two&/pagetwo/g
s/?page=three&/pagethree/g

a.txt:

?page=one&
?page=two&
?page=three&

Contenuto di b.txt dopo aver eseguito il comando sed:

pageone
pagetwo
pagethree

Cosa voglio che b.txt contenga:

/page/one
/page/two
/page/three


3
possibile duplicato di Usa barre in sed sostituzione
tripleee

Risposte:


274

Il modo più semplice sarebbe utilizzare un delimitatore diverso nella ricerca / sostituzione delle righe, ad es.

s:?page=one&:pageone:g

Puoi usare qualsiasi carattere come delimitatore che non fa parte di nessuna stringa. Oppure, potresti evitarlo con una barra rovesciata:

s/\//foo/

Che rimpiazzerebbe /con foo. Si desidera utilizzare la barra rovesciata con escape nei casi in cui non si conoscono i caratteri che potrebbero verificarsi nelle stringhe di sostituzione (se si tratta di variabili shell, ad esempio).


1
> Oppure potresti evitarlo con una barra rovesciata. Un esempio sarebbe più utile, dal momento che non sai sempre quali caratteri sono in una stringa per poter scegliere qualcosa di diverso. ad esempio, questo: echo / | sed s / \ // a / g non funziona: sed: -e espressione # 1, carattere 5: opzione sconosciuta a `s '
Max Waterman

1
Potresti aggiungerne uno allora? Grazie :) Ho trovato che circonda tra virgolette doppie sembra funzionare: echo / | sed "s / \ // a / g"
Max Waterman

@MaxWaterman è una procedura operativa standard quando si utilizza sedil comando regex tra virgolette doppie. Non li ho usati nella mia risposta perché non mostravo l'intera sedriga di comando ma solo la sedstringa di comando regex come aveva fatto l'OP. Se lo metti in un file, come ha fatto l'OP, non hai bisogno delle virgolette.
agguato il

Sì, abbastanza giusto (anche se forse potrebbe essere menzionato). Questo esempio aiuta. Ho scoperto che ho bisogno di inserire un sacco di barre rovesciate a volte ... e diventa davvero confuso. es. -e "s / '/ \\\\\\\ & / g" Penso che il testo sia sbagliato, però: "Che sostituirà \ con pippo" - dovrebbe essere "Che rimpiazzerebbe / con pippo", no?
Max Waterman,

@MaxWaterman grazie per averlo scoperto su \ vs. /. Aggiustato. Se si dispone di un sedcomando in uno script di shell, potrebbero essere necessarie più barre rovesciate (ogni barra rovesciata deve essere nuovamente barrata).
agguato il

105

Il scomando può usare qualsiasi carattere come delimitatore; qualunque personaggio venga dopo che sviene usato. Sono stato educato a usare a #. Così:

s#?page=one&#/page/one#g

5
La pagina man per la BSD sed su OS X dice del comando s : Sostituisci la stringa di sostituzione per la prima istanza dell'espressione regolare nello spazio del modello. È possibile utilizzare qualsiasi carattere diverso da barra rovesciata o newline anziché una barra per delimitare RE e la sostituzione. Scommetto che la pagina man di GNU sed dice qualcosa di simile.
Tom Anderson,

La risposta attualmente accettata è sostanzialmente la stessa di questa, ed è stata pubblicata un minuto prima!
Tom Anderson,

61

Un fatto molto utile ma meno noto su sed è che il s/foo/bar/comando familiare può usare qualsiasi punteggiatura, non solo barre. Un'alternativa comune è s@foo@bar@, da cui diventa ovvio come risolvere il tuo problema.


Consigli Genius quando si desidera sostituire le barre in avanti. Grazie!
mbb

9

aggiungi \ prima dei caratteri speciali:

s/\?page=one&/page\/one\//g

eccetera.


4
Potrei essermi perso qualcosa, ma ci ho provato e non sembra funzionare. Sembrava ovvio provare, ma supponendo che io abbia ragione e in effetti non funziona, perché pubblicarlo?
codenoob,

4
@codenoob (e chiunque altro venga qui) - è richiesta la 's' all'inizio. s/foo\/bar/foo_bar/funzionerà, ma /foo\/bar/foo_bar/non lo farà.
MynockSpit

5

In un sistema che sto sviluppando, la stringa che deve essere sostituita da sed è il testo di input di un utente che viene archiviato in una variabile e passato a sed.

Come notato in precedenza in questo post, se la stringa contenuta nel blocco di comando sed contiene l'effettivo delimitatore utilizzato da sed, allora sed termina in caso di errore di sintassi. Considera il seguente esempio:

Questo funziona:

$ VALUE=12345
$ echo "MyVar=%DEF_VALUE%" | sed -e s/%DEF_VALUE%/${VALUE}/g
MyVar=12345

Questo si rompe:

$ VALUE=12345/6
$ echo "MyVar=%DEF_VALUE%" | sed -e s/%DEF_VALUE%/${VALUE}/g
sed: -e expression #1, char 21: unknown option to `s'

La sostituzione del delimitatore predefinito non è una soluzione affidabile nel mio caso in quanto non volevo limitare l'utente a immettere caratteri specifici utilizzati da sed come delimitatore (ad esempio "/").

Tuttavia, l'escape di qualsiasi occorrenza del delimitatore nella stringa di input risolverebbe il problema. Si consideri la soluzione seguente di escape sistematica del carattere delimitatore nella stringa di input prima di averlo analizzato da sed. Tale escape può essere implementato come una sostituzione usando sed stesso, questa sostituzione è sicura anche se la stringa di input contiene il delimitatore - questo perché la stringa di input non fa parte del blocco di comandi sed:

$ VALUE=$(echo ${VALUE} | sed -e "s#/#\\\/#g")
$ echo "MyVar=%DEF_VALUE%" | sed -e s/%DEF_VALUE%/${VALUE}/g
MyVar=12345/6

Ho convertito questo in una funzione che può essere utilizzata da vari script:

escapeForwardSlashes() {

     # Validate parameters
     if [ -z "$1" ]
     then
             echo -e "Error - no parameter specified!"
             return 1
     fi

     # Perform replacement
     echo ${1} | sed -e "s#/#\\\/#g"
     return 0
}

1
La risposta per me è stata che se il VALUE che stai utilizzando per sostituire DEF_VALUE, contiene barre rovesciate, devi scappare con 3 barre rovesciate per far funzionare sed ad es.VALUE="01\\\/01\\\/2018"
alexkb

3

questa linea dovrebbe funzionare per i tuoi 3 esempi:

sed -r 's#\?(page)=([^&]*)&#/\1/\2#g' a.txt
  • Prima -rrisparmiavo qualche evasione.
  • la linea dovrebbe essere generica per il tuo caso, due tre. non devi fare il sub 3 volte

prova con il tuo esempio (a.txt):

kent$  echo "?page=one&
?page=two&
?page=three&"|sed -r 's#\?(page)=([^&]*)&#/\1/\2#g'
/page/one
/page/two
/page/three


1

Ottima risposta di Anonimo. \ ho risolto il mio problema quando ho cercato di sfuggire alle virgolette nelle stringhe HTML.

Quindi, se usi sed per restituire alcuni template HTML (su un server), usa una doppia barra rovesciata anziché singola:

var htmlTemplate = "<div style=\\"color:green;\\"></div>";

1

sedè il s tream ed itor , in quanto è possibile utilizzare |(pipe) per inviare flussi standard (STDIN e STDOUT in particolare) attraverso sede modificare a livello di codice al volo, che lo rende uno strumento utile nella tradizione filosofia Unix; ma può anche modificare direttamente i file utilizzando il -iparametro menzionato di seguito.
Considera quanto segue :

sed -i -e 's/few/asd/g' hello.txt

s/è usato per s ubstitute l'espressione che si ritrovafew con asd:

I pochi, i coraggiosi.


Il asd, il coraggioso.

/gsta per "globale", che significa farlo per l'intera linea. Se si interrompe il /g(con s/few/asd/, ci devono sempre essere tre barre a prescindere) e fewappare due volte sulla stessa linea, solo la prima fewviene cambiata in asd:

I pochi uomini, le poche donne, i coraggiosi.


Gli uomini asd, le poche donne, i coraggiosi.

Ciò è utile in alcune circostanze, come la modifica di caratteri speciali all'inizio delle righe (ad esempio, la sostituzione dei simboli maggiore di quelli che alcune persone usano per citare il materiale precedente nei thread di posta elettronica con una scheda orizzontale lasciando una disuguaglianza algebrica citata più avanti nella riga intatto), ma nel tuo esempio in cui lo specifichi ovunque few verifichi dovrebbe essere sostituito, assicurati di averlo /g.

Le seguenti due opzioni (flag) sono combinate in una, -ie :

-iopzione viene utilizzata per modificare i n posto sul filehello.txt .

-eopzione indica la e / comando di Xpression a correre, in questo caso s/.

Nota: è importante utilizzare -i -eper cercare / sostituire. In tal caso -ie, si crea un backup di ogni file con la lettera 'e' allegata.


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.