#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 hace lo anterior, dados los datos que muestra, antes de la última línea de limpieza allí, debería estar trabajando con un sed
espacio de patrón que se vea así:
^\n<tag1>\n<tag2>foo</tag2>\n</tag1>$
Puede imprimir su espacio de patrón cuando lo desee con l
ook. Luego puede abordar los \n
caracteres.
sed l <file
Le mostrará que cada línea la sed
procesa en la etapa en la que l
se llama.
Así que lo acabo de probar y necesitaba uno más \backslash
después ,comma
de la primera línea, pero por lo demás funciona como está. Aquí lo puse en un _sed_function
para que pueda llamarlo fácilmente con fines de demostración a lo largo de esta respuesta: (funciona con comentarios incluidos, pero aquí se eliminan por razones de brevedad)
_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>
Ahora cambiaremos el p
por un l
para que podamos ver con qué estamos trabajando mientras desarrollamos nuestro script y eliminamos la demostración no operativa s?
para que la última línea de nuestro sed 3<<\SCRIPT
simplemente se vea así:
l;s/.*//;h;b}}
Luego lo volveré a ejecutar:
_sed_function
#OUTPUT#
\n<tag1>\n <tag2>foo</tag2>\n</tag1>$
¡Okay! Así que tenía razón, es un buen sentimiento. Ahora, barajemos nuestro l
ook para ver las líneas que tira pero elimina. Eliminaremos nuestra actual l
y agregaremos una para !{block}
que se vea así:
!{l;s/.*//;h;b}
_sed_function
#OUTPUT#
\n<tag1>\n <tag2>bar</tag2>\n</tag1>$
Eso es lo que parece justo antes de que lo eliminemos.
Una última cosa que quiero mostrarles es el H
viejo espacio a medida que lo construimos. Hay un par de conceptos clave que espero poder demostrar. Así que elimino el último l
ook nuevamente y modifico la primera línea para agregar un vistazo al H
espacio anterior al final:
{ 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
el espacio antiguo sobrevive a los ciclos de línea, de ahí el nombre. Entonces, lo que la gente a menudo tropieza, está bien, lo que a menudo tropiezo es que necesita eliminarse después de usarlo. En este caso, solo x
cambio e una vez, por lo que el espacio de espera se convierte en el espacio del patrón y viceversa, y este cambio también sobrevive a los ciclos de línea.
El efecto es que necesito eliminar mi espacio de espera que solía ser mi espacio de patrón. Hago esto limpiando primero el espacio de patrón actual con:
s/.*//
Que simplemente selecciona cada personaje y lo elimina. No puedo usarlo d
porque esto terminaría mi ciclo de línea actual y el siguiente comando no se completaría, lo que prácticamente destruiría mi script.
h
Esto funciona de manera similar, H
pero sobrescribe el espacio de retención, por lo que acabo de copiar mi espacio de patrón en blanco sobre la parte superior de mi espacio de retención, eliminándolo efectivamente. Ahora solo puedo:
b
fuera.
Y así es como escribo sed
guiones.