У меня есть похожие инструкции, как в теме Print Matching line and nth line from the matched line
Мне нужно найти определенную строку, напечатать ее, затем удалить следующую строку (1-я следующая строка), а затем напечатать остальные до совпадения с определенной строкой и т.д.
Другими словами, мне нужно удалить только строки с , которые следуют за строкой, начинающейся с
Мой файл:
Bla
bla
bla
.
Bla
bla
bla
.
...
Мой требуемый вывод:
Bla
bla
bla
.
Bla
bla
bla
.
...
С GNUsed
:
sed -z -i 's:<doc>\n</s>:<doc>:g' infile.txt
Это заменяет <doc>
, за которым следует </s>
, только на <doc>
. Флаг sed
-i
используется для замены на месте; а флаг g
заменяет все вхождения . -z
заставляют разделять строки символами NULL.
Как вы отметили shell_script
, я бы предложилawkподход:
awk '/^<doc>/ && getline nl > 0 && nl!~/^<\/s>/{ print $0 RS nl }1' file
Выход:
<doc>
<s>
Bla
bla
bla
.
</s>
<s>
Bla
bla
bla
.
</s>
</doc>
<doc>
...
Это несложно понять, имея базовые sed
знания:
sed '/<doc>/{n;/<\/s>/d;}'
Для строк с <doc>
распечатайте его и прочитайте следующую строку с n
, а затем, если эта следующая строка содержит </s>
(, необходимо экранировать косую черту ), удалите ее с помощью d
.
Более подробное объяснение:/expression/{command;command;...;}
означает выполнение команд только в строках, соответствующих шаблону, поэтому все остальные строки просто печатаются как есть, а для строки <doc>
выполняется n
. Эта команда печатает текущую строку и читает следующую, поэтому следующие команды выполняются в следующей строке. Здесь идет другая команда(d
)с "адресом" (/<\/s>/
), поэтому строка d
удаляется, только если она содержит </s>
, в противном случае печатается. В любом случае сценарий продолжится со следующей строки.