#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
Якщо ви зробите вищезазначене, враховуючи дані, які ви показуєте, перед останнім рядком очищення там, вам слід працювати з sedшаблоном, який виглядає так:
^\n<tag1>\n<tag2>foo</tag2>\n</tag1>$
Ви можете роздрукувати простір шаблону, коли завгодно, з lдубом. Потім можна звертатися до \nсимволів.
sed l <file
Покаже вам, що кожен рядок sedобробляє його на етапі, на який lвикликається.
Тож я щойно перевірив це, і він потребував ще одного \backslashпісля ,commaпершого рядка, але в іншому випадку працює як є. Ось я поклав це _sed_functionтак, що я можу легко назвати це з метою демонстрації протягом усієї цієї відповіді: (працює з коментарями, включені, але тут видалено заради стислості)
_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>
Тепер ми будемо перемикати pдля lтаким чином , ми можемо бачити , що ми працюємо з , як ми розвиваємо наш сценарій і видалити , НЕ оп демо s?так в останньому рядку нашого sed 3<<\SCRIPTвиглядає як:
l;s/.*//;h;b}}
Тоді я запускаю його ще раз:
_sed_function
#OUTPUT#
\n<tag1>\n <tag2>foo</tag2>\n</tag1>$
Добре! Тож я мав рацію - це гарне почуття. Тепер давайте перемістимо наш lдуб навколо, щоб побачити лінії, які він тягне, але видаляє. Ми видалимо наш поточний lі додамо його, !{block}щоб він виглядав так:
!{l;s/.*//;h;b}
_sed_function
#OUTPUT#
\n<tag1>\n <tag2>bar</tag2>\n</tag1>$
Ось як це виглядає безпосередньо перед тим, як ми їх витираємо.
Останнє, що я хочу вам показати, - це Hстарий простір під час його створення. Є кілька ключових понять, які я сподіваюся продемонструвати. Тому я lзнову видаляю останній ок і змінюю перший рядок, щоб додати заглянути до Hстарого простору наприкінці:
{ 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старий простір переживає лінійні цикли - звідси і назва. Тому те, що люди часто виходять з ладу - добре, те, що я часто піднімаю, - це те, що його потрібно видалити після того, як ви його використовуєте. У цьому випадку я змінююсь лише xодин раз, тому простір утримування стає простором шаблону і навпаки, і ця зміна також переживає лінійні цикли.
Ефект полягає в тому, що мені потрібно видалити простір утримування, який раніше був моїм шаром. Я роблю це, спочатку очищаючи поточний простір шаблону за допомогою:
s/.*//
Що просто вибирає кожного персонажа і видаляє його. Я не можу використовувати, dтому що це завершить мій поточний цикл рядків, і наступна команда не буде виконана, що в значній мірі втратить мій сценарій.
h
Це працює аналогічно тому, Hале він перезаписує простір утримування, тому я просто скопіював мій простір шаблону у верхню частину простору утримування, ефективно видаляючи його. Тепер я можу просто:
b
з.
І саме так я пишу sedсценарії.