#begin command block
#append all lines between two addresses to hold space
sed -n -f - <<\SCRIPT file.xml
\|<tag1>|,\|</tag1>|{ H
#at last line of search block exchange hold and pattern space
\|</tag1>|{ x
#if not conditional ; clear buffer ; branch to script end
\|<tag2>[^<]*foo[^\n]*</tag2>|!{s/.*//;h;b}
#do work ; print result; clear buffer ; close blocks
s?*?*?;p;s/.*//;h;b}}
SCRIPT
Si vous faites ce qui précède, compte tenu des données que vous affichez, avant cette dernière ligne de nettoyage, vous devriez travailler avec un sed
espace de modèle qui ressemble à:
^\n<tag1>\n<tag2>foo</tag2>\n</tag1>$
Vous pouvez imprimer votre espace de motif à tout moment avec l
ook. Vous pouvez ensuite vous adresser aux \n
personnages.
sed l <file
Vous montrera que chaque ligne la sed
traite au stade où elle l
est appelée.
Je viens donc de le tester et il en fallait un de plus \backslash
après ,comma
la première ligne, mais sinon il fonctionne tel quel . Ici, je le mets dans un _sed_function
afin que je puisse facilement l'appeler à des fins de démonstration tout au long de cette réponse: (fonctionne avec les commentaires inclus, mais sont supprimés ici par souci de concision)
_sed_function() { sed -n -f /dev/fd/3
} 3<<\SCRIPT <<\FILE
\|<tag1>|,\|</tag1>|{ H
\|</tag1>|{ x
\|<tag2>[^<]*foo[^\n]*</tag2>|!{s/.*//;h;b}
s?*?*?;p;s/.*//;h;b}}
#END
SCRIPT
<tag1>
<tag2>bar</tag2>
</tag1>
<tag1>
<tag2>foo</tag2>
</tag1>
FILE
_sed_function
#OUTPUT#
<tag1>
<tag2>foo</tag2>
</tag1>
Maintenant, nous allons changer le p
pour un l
afin que nous puissions voir avec quoi nous travaillons pendant que nous développons notre script et supprimons la démo non-op s?
pour que la dernière ligne de notre sed 3<<\SCRIPT
ressemble à ceci :
l;s/.*//;h;b}}
Ensuite, je vais l'exécuter à nouveau:
_sed_function
#OUTPUT#
\n<tag1>\n <tag2>foo</tag2>\n</tag1>$
D'accord! J'avais donc raison - c'est un bon sentiment. Maintenant, mélangeons notre l
regard pour voir les lignes qu'il tire mais supprime. Nous allons supprimer notre courant l
et en ajouter un pour !{block}
qu'il ressemble à ceci:
!{l;s/.*//;h;b}
_sed_function
#OUTPUT#
\n<tag1>\n <tag2>bar</tag2>\n</tag1>$
Voilà à quoi cela ressemble juste avant de l'effacer.
Une dernière chose que je veux vous montrer est l' H
ancien espace que nous construisons. Il y a quelques concepts clés que j'espère pouvoir démontrer. Je retire donc le dernier l
ook et modifie la première ligne pour ajouter un aperçu dans l' H
ancien espace à la fin:
{ H ; x ; l ; x
_sed_function
#OUTPUT#
\n<tag1>$
\n<tag1>\n <tag2>bar</tag2>$
\n<tag1>\n <tag2>bar</tag2>\n</tag1>$
\n<tag1>$
\n<tag1>\n <tag2>foo</tag2>$
\n<tag1>\n <tag2>foo</tag2>\n</tag1>$
H
le vieil espace survit aux cycles des lignes - d'où son nom. Donc, ce que les gens font souvent trébucher - ok, ce que je fais souvent trébucher - c'est qu'il faut le supprimer après l'avoir utilisé. Dans ce cas, je ne x
change qu'une seule fois, donc l'espace de maintien devient l'espace de motif et vice-versa et ce changement survit également aux cycles de ligne.
L'effet est que je dois supprimer mon espace d'attente qui était mon espace de motif. Pour ce faire, je vide d'abord l'espace de motif actuel avec:
s/.*//
Qui sélectionne simplement chaque personnage et le supprime. Je ne peux pas l'utiliser d
car cela mettrait fin à mon cycle de ligne en cours et la prochaine commande ne se terminerait pas, ce qui mettrait à peu près à la poubelle mon script.
h
Cela fonctionne de manière similaire à H
mais il écrase l' espace de rétention , donc je viens de copier mon espace de motif vierge au-dessus de mon espace de rétention, le supprimant efficacement. Maintenant je peux juste:
b
en dehors.
Et c'est comme ça que j'écris des sed
scripts.