SED sostituisce su più righe


11

Sto cercando di trovare queste tre righe:

<!--
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
-->

e sostituirli con:

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

Quando ci provo

sudo sed -i 's:<!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->:<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />:' /myfile.xml

Non lo trova, ho anche provato a inserirlo \, ma non ha ancora funzionato:

sudo sed -i 's:<!--\n <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />\n -->:<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />:' /myfile.xml

Questi non generano errori, ma non togliono il commento alla linea. Qualsiasi consiglio aiuterebbe grazie!

Risposte:


6

sed legge ogni riga a turno, quindi non corrisponderà mai a un modello multilinea se non lo spingi nella giusta direzione. Il Ncomando legge una riga dall'input e la aggiunge allo spazio del pattern.

sed -i -e '/^<!--$/ {
    N; /\n<Connector port="8009" protocol="AJP\/1\.3" redirectPort="8443" \/>$/ {
        N; /\n-->$/ {
            s/^<!--\n//; s/\n-->$//
        }
    }
}' /myfile.xml

Probabilmente, se hai bisogno di un comando diverso da s, allora dovresti passare da sed a awk o perl. Ecco uno snippet Perl leggermente più flessibile che gestisce i commenti su più righe in un modo più generale.

perl -i -pe '
    if (/<!--/) { $_ .= <> while !/-->/;
        s[<!--\n(<Connector port="8009" protocol="AJP/1\.3" redirectPort="8443" />)\n-->][$1];
    }' /myfile.xml

6

Sed lavora riga per riga. Può essere fatto funzionare su più linee, ma non è stato progettato in questo modo - e secondo me mostra sicuramente quando si tenta di usarlo in quel modo. Ma se decidi di andare in quel modo probabilmente dovrai usare i registri. Controlla alcune delle soluzioni su /programming/1251999/sed-how-can-i-replace-a-newline-n per vedere come si può fare.

Preferisco usare perl invece di sed per questo tipo di attività (orientata a più linee, intendo). La piastra della caldaia che devi aggiungere prima di cerca e sostituisci ( BEGIN...) non è ovvia, ma il regex mi sembra più pulito:

perl -i.bak -pe 'BEGIN{undef $/;} s/<!--string-->/string/smg' file.xml

Oppure, usando il raggruppamento per abbreviare l'espressione e per permetterti di usare una regex lì:

perl -i.bak -pe 'BEGIN{undef $/;} s/<!--(string_or_regex)-->/\1/smg' file.xml

Dovrebbe funzionare sia su occorrenze con e senza newline tra i marcatori di commento e il codice per essere decommentato.

Adattato da:

/programming/1030787/multiline-search-replace-with-perl


Grazie per il tuo aiuto, sembra che sia un dolore, ho deciso di usare una soluzione alternativa
Doug Molineux,


1
  • /<\!--/ : stringa corrispondente
  • :X : questa è un'etichetta per il comando branch "b"
  • /-->/ : stringa corrispondente
  • s@...@...@p : striscia "<! -", "->" e stampa il risultato
  • d : cancella lo spazio del motivo e avvia un nuovo ciclo
  • N : se non corrisponde a / -> /, aggiungi una riga
  • bX : ramo a: etichetta X.
  • p : basta stampare una stringa che non corrisponde a / <! - /

sed -rn '
/<!--/ {
    :X
    /-->/ {
        s@<!--\s*(<.+/>)\s*-->@\1@p
        d
    }
    N
    bX
};p'

e questo secondo metodo è una semplice sostituzione copia e incolla testuale per normali file di testo di piccole dimensioni (è necessario un file di script shell)

#!/bin/bash

# copy & paste content that you want to substitute

AA=$( cat <<\EOF | sed -z -e 's#\([][^$*\.#]\)#\\\1#g' -e 's#\n#\\n#g'
<!--
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
-->
EOF
)

BB=$( cat <<\EOF | sed -z -e 's#\([&\#]\)#\\\1#g' -e 's#\n#\\n#g'
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
EOF
)

sed -z -i 's#'"${AA}"'#'"${BB}"'#g' *.xml   # apply to all *.xml files

1) Grazie per la risposta. 2) Inserire solo frammenti di codice non va bene, sarebbe molto meglio se tu spiegassi, cosa fa e come.
Peter - Ripristina Monica il
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.