Как выбрать первое вхождение между двумя образцами, включая их

27

Как я могу выбрать первое вхождение между двумя образцами, включая их. Предпочтительно с помощью sedили awk.

Я имею:

text
something P1 something
content1
content2
something P2 something
text
something P1 something
content3
content4
something P2 something
text

Я хочу, чтобы первое вхождение линий между P1 и P2 (включая линию P1 и линию P2):

something P1 something
content1
content2
something P2 something
kofucii
источник

Ответы:

22
sed '/P1/,/P2/!d;/P2/q'

... выполнит работу переносимо, выбрав dвсе строки, которые !не попадают в диапазон, а затем qвыбрав первый раз, когда он достигнет конца диапазона. Он не терпит неудачу для P2, предшествующего P1, и не требует специального синтаксиса GNU для простой записи.

mikeserv
источник
Превосходно! Гораздо лучше, чем у меня.
Муру
1
@muru - часто легче избежать искажений, если вы пытаетесь нацелиться на автопринт - пусть цикл работает для вас. Это привычка, в которую я все равно впал. Я думаю, что это, вероятно, лучше всего описать как чернослив против метода выбора - я склонен в конечном итоге отрицать шаблон, а не искать его.
mikeserv
Это будет зависать при обработке огромного fileSize.
Brain90
@ Brain90 - не должен. если вы можете надежно воспроизвести вашу жалобу, вам следует обратиться к сопровождающему вашего sed... это ошибка в sedзапущенной вами версии , а не в сценарии tbe выше.
mikeserv
1
@mikeserv Я бы не сказал этого, если бы не был. Вы беспокоитесь о том, волнует ли меня пара символов или нет: я заметил, что выражение sed работает как /P2/qв моей системе, так и без нее; вот и все. Мне было интересно о чем-то, и я хотел поделиться тем, что нашел.
Алексей Магура
8

с awk

awk '/P1/{a=1};a;/P2/{exit}' file
something P1 something
content1
content2
something P2 something
Iruvar
источник
8

В sed:

sed -n '/P1/,/P2/p; /P2/q'
  • -nподавляет печать по умолчанию, и вы печатаете строки между совпадающими диапазонами адресов с помощью pкоманды.
  • Обычно это соответствует обоим разделам, поэтому вы выходите ( q) при первом P2совпадении.

Это не удастся, если P2приходит раньше P1. Чтобы справиться с этим делом, попробуйте:

sed -n '/P1/,/P2/{p; /P2/q}'
Мур
источник
1
Я не согласен; Ответ mikeserv не лучше, чем ваш.
G-Man говорит: «Восстанови Монику»
@ g-man - pshaw. но я просто думал о том же.
mikeserv
1
@ gman - нет. Теперь я понимаю. мин лучше. нет {стека}!
Mikeserv
1

Если вы хотите пропустить сами шаблоны, вот awkверсия:

awk '/P2/ {exit} /P1/ {f=1; next} f' file
codeforester
источник
Работает для меня. Не могли бы вы добавить больше информации о том, как работает команда?
0xAffe
1

Более простое awkрешение (рода- на полпути между ответом Iruvar в и  ответе Мура в , но не использует переменный):

awk '/P1/,/P2/ { print }  /P2/ { exit }'

и, как отметил Муру, если первый P2 появится перед первым P1, это ничего не напечатает.

Конечно, если вы хотите распечатать все диапазоны P1-P2:

something P1 something
content1
content2
something P2 something
something P1 something
content3
content4
something P2 something

просто пропустите exitчасть:

awk '/P1/,/P2/ { print }'
G-Man говорит: «Восстанови Монику»
источник
1
awk '/P1/,/P2/{print;f=1} f&&/P2/{exit}' data

Выйти сразу после печати, а не до.

dedowsdi
источник
0

Чтобы пропустить сами шаблоны и показать только первый соответствующий блок в одном GNU sed:

sed -nre '/STARTPATTERN/ {:a;n;/ENDPATTERN/{b;};p;ba}' file
Santrix
источник