Исключая первую и последнюю строки из sed/START/,/END/
Рассмотрим вход:
=sec1=
some-line
some-other-line
foo
bar=baz
=sec2=
c=baz
Если я хочу обработать только = sec1 =, я могу, например, закомментировать раздел:
sed -e '/=sec1=/,/=[a-z]*=/s:^:#:' < input
... ну, почти.
Это будет прокомментировать строки, включая строки "= sec1 =" и "= sec2 =", и результат будет примерно таким:
#=sec1=
#some-line
#some-other-line
#
#foo
#bar=baz
#
#=sec2=
c=baz
Мой вопрос: Самый простой способ исключить начальную и конечную строки из /START/,/END/range в sed?
Я знаю, что для многих случаев уточнение "s:" когтей может дать решение в этом конкретном случае, но я следую за общим решением здесь.
В " Sed - введение и учебник" Брюс Барнетт пишет: "Я покажу вам, как ограничить команду до, но не включая строку, содержащую указанный шаблон.", но я не смог найти, где он на самом деле показывает это.
В ПОЛЕЗНЫЕ ОДНОГРАНИЧНЫЕ СЦЕНАРИИ ДЛЯ СЕПА" Составив Эрика Пемца, я мог бы найти только инклюзивный пример:
# print section of file between two regular expressions (inclusive)
sed -n '/Iowa/,/Montana/p' # case sensitive
Ответы
Ответ 1
Это должно сделать трюк:
sed -e '/=sec1=/,/=sec2=/ { /=sec1=/b; /=sec2=/b; s/^/#/ }' < input
Это совпадение между sec1 и sec2 включительно, а затем просто пропускает первую и последнюю строку с помощью команды b
. Это оставляет желаемые строки между sec1 и sec2 (exclusive), а команда s
добавляет знак комментария.
К сожалению, вам нужно повторить регулярные выражения для соответствия разделителей. Насколько я знаю, нет лучшего способа сделать это. По крайней мере, вы можете держать регулярные выражения чистыми, даже если они используются дважды.
Это адаптировано из Часто задаваемые вопросы SED: как мне адресовать все строки между RE1 и RE2, за исключением самих строк?
Ответ 2
Если вас не интересуют строки за пределами диапазона, но просто хотите, чтобы не включительный вариант примера из Айовы/Монтаны из вопроса (что и привело меня сюда), вы можете написать "за исключением первый и последний совпадающие строки" достаточно легко со вторым sed:
sed -n '/PATTERN1/,/PATTERN2/p' < input | sed '1d;$d'
Лично я нахожу это немного яснее (хотя и медленнее на больших файлах), чем эквивалент
sed -n '1,/PATTERN1/d;/PATTERN2/q;p' < input
Ответ 3
Другой способ:
sed '/begin/,/end/ {
/begin/n
/end/ !p
}'
/begin/n
→ пропустить строку, которая имеет шаблон "начать"
/end/ !p
→ распечатать все строки, которые не имеют шаблона "end"
Взято из учебника Bruce Barnett sed http://www.grymoire.com/Unix/Sed.html#toc-uh-35a
Ответ 4
вы также можете использовать awk
awk '/sec1/{f=1;print;next}f && !/sec2/{ $0="#"$0}/sec2/{f=0}1' file
Ответ 5
Я использовал:
sed '/begin/,/end/{/begin\|end/!p}'
Это приведет к поиску всех строк между шаблонами, затем распечатает все, что не содержит шаблонов