с Perl
:
perl -0ne 'END {print $.}'
или:
perl -nle 'print scalar split "\0"'
или:
perl -nle 'print scalar unpack "(Z*)*", $_'
Обработка XML в качестве текста, как правило, не является надежным решением, но если вы настаиваете на том, что вы, возможно, можете воспользоваться пространством удержания SED E.G.
sed -e '/<id>[0-9]*<\/id>/h' -e '/<root>/{x;p;x;}' file.xml
Решение с использованием awk
будет
awk '/<id>/{id=$0}/<root>/{print id}1' file.xml
Если вы не хотите печатать
, вы можете пропустить Линия, добавив Далее
.
awk '/<id>/{id=$0;next}/<root>/{print id}1' file.xml
sed -e :b -e '$!{N;\|<id>.*\n<root>|!bb
};do what ever you want to do with all of those lines now....'
Я согласен со стилдрайвером, что h
oldspace, вероятно, лучший вариант, но есть и другие варианты. Иногда мы не можем побеспокоиться об управлении обоими буферами - или, как часто бывает в моей проблеме, мы уже управляем обоими буферами. Вышеуказанные фрагменты стекают линии в пространстве паттернов. Пока между тегами
всегда происходит , он всегда рекурсивно заполняет пространство паттерна нужным блоком данных перед переходом на 2-ю строку - , т.е. будет делать это до тех пор, пока буферы не взорвутся - но это довольно сложно сделать сейчас.
Также, возвращаясь к h
старой вещи пространства, ex
изменение действительно делает swap h
старой и шаблонной вещи. Используя его один раз, буфер шаблонов становится старым буфером h
и наоборот. Этот эффект выдерживает линейные циклы. Часто то, что я делаю, читаю в файле, пока не доберусь до стартовой строки, выполняю предварительные правки, затем своп и продолжаю ставить H
до тех пор, пока не получу другую. Когда мой скрипт поменяет местами обратно, он наматывает блок сзади - на последнем маркере, который я включил, плюс все H
старые за это время. Это простой способ буферизации только столько, сколько необходимо, когда вы должны.
И так, другой способ реализации цикла, как вы хотите:
sed -e '/<id>/h;//!H;/<root>/!{$!d' -e '};x...'
С этой точки на пространстве шаблона находится H
старое пространство и наоборот. h
old will overwrite h
old space with current pattern space whenever it used - так что приведенный выше пример каждый раз начинает свежий буфер со строкой
. !H
добавляет все промежуточные строки к H
старому пространству, каждая из которых следует за символом \n
ewline. $!d
поднимает пробел в каждой строке, которая является !
не последний раз $
, когда текущая строка благополучно H
старше и начинает следующий цикл строк, и поэтому ex
изменение происходит только на совпадениях <корень>
, к которому весь блок ждет вас.
Просто имейте в виду, что на вашем самом последнем блоке , ваш маркер, вероятно, последняя строка, в случае, если она отличается от совпадений
.
Но...
Согласно вашему редактированию, я не вижу причин, по которым вам не удалось уйти:
sed '/<id>/h;//d;\|</root>|G
' <<\INPUT
unimportant 1
<id> number 1 </id>
<root> sub text
more text
more text
</root>
<root> sub text as well
and more text
and more text
</root>
unimportant 2
<id> number 2 </id>
<root> sub text
more text
more text
</root>
<root> sub text
and more text
and more text
</root>
INPUT
Там
строки - это h
старые (опять же: перезапись h
старого места), а затем d
возведенные из вывода. Когда происходит совпадение ,
sed
G
ets старое пространство h
добавленное к пространству шаблонов перед автоматической печатью результатов в конце линейного цикла, который выглядит так:
unimportant 1
<root> sub text
more text
more text
</root>
<id> number 1 </id>
<root> sub text as well
and more text
and more text
</root>
<id> number 1 </id>
unimportant 2
<root> sub text
more text
more text
</root>
<id> number 2 </id>
<root> sub text
and more text
and more text
</root>
<id> number 2 </id>