#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
Se fai quanto sopra, dati i dati che mostri, prima dell'ultima riga di pulizia lì, dovresti lavorare con uno sedspazio modello simile a:
^\n<tag1>\n<tag2>foo</tag2>\n</tag1>$
Puoi stampare lo spazio del tuo motivo ogni volta che vuoi con look. È quindi possibile indirizzare i \ncaratteri.
sed l <file
Ti mostrerà ogni linea lo sedelabora nella fase in cui lviene chiamato.
Quindi l'ho appena testato e ne ho avuto bisogno \backslashdopo uno ,commanella prima riga, ma per il resto funziona così. Qui lo inserisco in _sed_functionmodo da poterlo facilmente chiamare a scopo dimostrativo in tutta questa risposta: (funziona con commenti inclusi, ma qui sono rimossi per brevità)
_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>
Ora cambiamo il pper un lcosì possiamo vedere con cosa stiamo lavorando mentre sviluppiamo il nostro script e rimuoviamo la demo non-op in s?modo che l'ultima riga del nostro sed 3<<\SCRIPTassomigli a:
l;s/.*//;h;b}}
Quindi lo eseguirò di nuovo:
_sed_function
#OUTPUT#
\n<tag1>\n <tag2>foo</tag2>\n</tag1>$
Ok! Quindi avevo ragione, è una bella sensazione. Ora, mescoliamo il nostro look in giro per vedere le linee che tira dentro ma cancella. Rimuoveremo la nostra corrente le ne aggiungeremo una in !{block}modo che assomigli a:
!{l;s/.*//;h;b}
_sed_function
#OUTPUT#
\n<tag1>\n <tag2>bar</tag2>\n</tag1>$
Ecco come appare poco prima di cancellarlo.
Un'ultima cosa che voglio mostrarti è il Hvecchio spazio mentre lo costruiamo. Ci sono un paio di concetti chiave che spero di poter dimostrare. Quindi rimuovo di nuovo l'ultimo look e modifico la prima riga per aggiungere una sbirciatina nel Hvecchio spazio alla fine:
{ 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>$
Hil vecchio spazio sopravvive ai cicli di linea - da qui il nome. Quindi quello su cui la gente inciampa spesso - ok, quello su cui inciampo spesso - è che deve essere cancellato dopo averlo usato. In questo caso xcambio solo una volta, quindi lo spazio di mantenimento diventa lo spazio del modello e viceversa e questo cambiamento sopravvive anche ai cicli di linea.
L'effetto è che devo eliminare il mio spazio di attesa che era il mio spazio modello. Lo faccio cancellando prima lo spazio del pattern corrente con:
s/.*//
Che seleziona semplicemente ogni personaggio e lo rimuove. Non posso usarlo dperché questo finirebbe il mio attuale ciclo di linee e il prossimo comando non sarebbe stato completato, il che avrebbe praticamente rovinato il mio script.
h
Funziona in modo simile Hma sovrascrive lo spazio di trattenimento, quindi ho appena copiato il mio spazio modello vuoto sopra lo spazio di trattenimento, eliminandolo in modo efficace. Ora posso solo:
b
su.
Ed è così che scrivo sedscript.