Remplacement SED sur plusieurs lignes


11

J'essaie de trouver ces trois lignes:

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

et remplacez-les par:

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

Quand j'essaye

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

Il ne le trouve pas, j'ai également essayé de le mettre \ n, mais cela n'a toujours pas fonctionné:

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

Ceux-ci ne génèrent aucune erreur, mais ne décommentent pas la ligne. Tout conseil serait utile merci!

Réponses:


6

sed lit chaque ligne tour à tour, donc elle ne correspondra jamais à un modèle multiligne à moins que vous ne la poussiez dans la bonne direction. La Ncommande lit une ligne de l'entrée et l'ajoute à l'espace de motif.

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

Sans doute, si vous avez besoin d'une commande autre que s, alors vous devriez passer de sed à awk ou perl. Voici un extrait de Perl légèrement plus flexible qui gère les commentaires multilignes de manière plus générale.

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

6

Sed fonctionne ligne par ligne. Il peut être fait pour fonctionner sur plusieurs lignes, mais il n'a pas été conçu de cette façon - et à mon avis, il apparaît clairement lorsque vous essayez d'utiliser comme ça. Mais si vous décidez de suivre cette voie, vous devrez probablement utiliser des registres. Consultez certaines des solutions de /programming/1251999/sed-how-can-i-replace-a-newline-n pour voir comment cela peut être fait.

Je préfère utiliser perl au lieu de sed pour ce genre de tâche (orientée sur plusieurs lignes, je veux dire). Le passe-partout que vous devez ajouter avant la recherche et le remplacement ( BEGIN...) n'est pas évident, mais l'expression régulière me semble plus propre:

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

Ou, en utilisant le regroupement pour raccourcir l'expression et pour vous permettre d'y utiliser une expression régulière:

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

Il devrait fonctionner à la fois sur les occurrences avec et sans sauts de ligne entre les marqueurs de commentaire et le code à ne pas commenter.

Adapté de:

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


Merci pour votre aide, on dirait que c'est une douleur, j'ai décidé d'utiliser une solution de contournement
Doug Molineux


1
  • /<\!--/ : chaîne correspondante
  • :X : c'est une étiquette pour la commande de branche "b"
  • /-->/ : chaîne correspondante
  • s@...@...@p : supprimer "<! -", "->" et imprimer le résultat
  • d : supprimer l'espace de motif et commencer un nouveau cycle
  • N : sinon correspondre avec / -> / puis ajouter une ligne
  • bX : branche vers: étiquette X
  • p : affiche simplement une chaîne qui ne correspond pas à / <! - /

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

et cette deuxième méthode est une simple substitution de copier-coller textuellement pour les fichiers texte habituels de petite taille (besoin d'un fichier de 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) Merci pour votre réponse. 2) L'insertion uniquement d'extraits de code n'est pas vraiment acceptable, il serait préférable que vous expliquiez ce qu'elle fait et comment.
peterh
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.