#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
Ook. Затем вы можете обратиться по \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
ook, чтобы увидеть строки, которые он вытягивает, но удаляет. Мы удалим наш текущий l
и добавим один к !{block}
так, чтобы это было похоже на:
!{l;s/.*//;h;b}
_sed_function
#OUTPUT#
\n<tag1>\n <tag2>bar</tag2>\n</tag1>$
Вот как это выглядит перед тем, как мы уничтожим это.
И последнее, что я хочу показать вам, это H
старое пространство, в котором мы его строим. Есть пара ключевых концепций, которые я надеюсь продемонстрировать. Поэтому я l
снова удаляю последний ook и изменяю первую строку, чтобы добавить заглядывание в 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
сценарии.