#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 sedespace de modèle qui ressemble à:
^\n<tag1>\n<tag2>foo</tag2>\n</tag1>$
Vous pouvez imprimer votre espace de motif à tout moment avec look. Vous pouvez ensuite vous adresser aux \npersonnages.
sed l <file
Vous montrera que chaque ligne la sedtraite au stade où elle lest appelée.
Je viens donc de le tester et il en fallait un de plus \backslashaprès ,commala première ligne, mais sinon il fonctionne tel quel . Ici, je le mets dans un _sed_functionafin 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 ppour un lafin 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<<\SCRIPTressemble à 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 lregard pour voir les lignes qu'il tire mais supprime. Nous allons supprimer notre courant let 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' Hancien espace que nous construisons. Il y a quelques concepts clés que j'espère pouvoir démontrer. Je retire donc le dernier look et modifie la première ligne pour ajouter un aperçu dans l' Hancien 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>$
Hle 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 xchange 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 dcar 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 à Hmais 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 sedscripts.