Как добавить линию перед совпадением в заданном диапазоне строк / шаблонах, используя sed? - PullRequest
1 голос
/ 15 января 2020

Я хочу сделать базовую c sed -линейную вставку, но без заданного диапазона строк.

Используя данный файл примера sample.txt:

foo
tomato
apple
bar
START_MARKER
tomato
apple
kiwifruit
pineapple
strawberry

END_MARKER

apple
qux

Я хочу добавить строку (скажем, «_____new_line_____») перед любой строкой между «START_MARKER» и «END_MARKER», содержащей «apple». Тогда мой образец стал бы:

foo
tomato
apple
bar
START_MARKER
tomato
_____new_line_____
apple
kiwifruit
_____new_line_____
pineapple
strawberry

END_MARKER

apple
qux

Я пытался:

sed '/^START_MARKER$/,/^END_MARKER$/ /apple/i _____new_line_____' sample.txt

Но я получаю:

sed: -e выражение # 1, символ 33 : неизвестная команда: `/ '

Также пробовал:

sed '/^START_MARKER$/,/^END_MARKER$/ {/apple/i _____new_line_____}' sample.txt

Но я получаю:

sed: -e выражение # 1, символ 0: не соответствует `{'

Если бы я хотел добавить строку" _____new_line_____ "перед всей строкой, содержащей" apple "(без использования START_MARKER и END_MARKER), сработало бы следующее:

sed '/apple/i _____new_line_____' sample.txt

Мне не хватает чего-то связать / объединить выбор шаблона / start /, / end / с моей операцией // i add-line.

Ответы [ 3 ]

1 голос
/ 15 января 2020

Вы можете использовать следующее:

sed '/START_MARKER/,/END_MARKER/!b;/apple/ i_____new_line_____' sample.txt > out

, где sed проходит через каждую строку, и если шаблон 'apple' находится в диапазоне START_MARKER и END_MARKER, он вставляет '_____new_line_____' перед 'яблоком и если шаблон «яблоко» не находится в диапазоне, то он ничего не делает.

Если вы не направите вывод в файл, он будет напечатан на экране терминала.

1 голос
/ 15 января 2020

С GNU sed

$ sed -e '/^START_MARKER$/,/^END_MARKER$/ { /apple/i _____new_line_____' -e '}' ip.txt
foo
tomato
apple
bar
START_MARKER
tomato
_____new_line_____
apple
kiwifruit
_____new_line_____
pineapple
strawberry

END_MARKER

apple
qux

Все, что после команды a/c/i, рассматривается в качестве аргумента этой команды. Итак, вам нужно разделить их, используя символ новой строки или -e, как показано выше. См. https://www.gnu.org/software/sed/manual/sed.html#Commands -Requing-a-newline для получения более подробной информации.


С другими sed это может работать, но не уверен, как я не могу проверить это:

sed '/^START_MARKER$/,/^END_MARKER$/ {
/apple/i\
_____new_line_____
}' ip.txt
0 голосов
/ 15 января 2020

Это может работать для вас (GNU sed):

sed -e '/START/{:a;n;/apple/i\__newline__' -e '/END/!ba}' file

Вставляет строку перед любой строкой, содержащей apple между START и END или концом файла.

Чтобы вставить строку только между START и END перед строкой, содержащей apple, используйте:

sed -e ':a;/\n/{/^[^\n]*apple/i\__newline__' -e 'P;D};/START/{:b;N;/END/!bb;ba}' file

Это собирает строки между START и END и только затем вставляет строку перед строками, содержащими apple.

...