Печать строк между (и исключая) двумя рисунками

13

Я собираюсь отправить форму с помощью cURL, где часть содержимого берется из другого файла, выбранного с помощью sed

Если param1используется шаблон совпадения строк из другого файла sed, команда ниже будет работать нормально:

curl -d param1="$(sed -n '/matchpattern/p' file.txt)" -d param2=value2 http://example.com/submit

Теперь перейдем к проблеме. Я хочу показать только текст между 2 соответствующими шаблонами, исключая сам соответствующий шаблон.

Скажем, file.txtсодержит:

Bla bla bla
firstmatch
It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.
secondmatch
The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English.

В настоящее время многие команды "Beetween 2 Match Pattern" sedне удаляются firstmatchи secondmatch.

Я хочу, чтобы результат стал:

It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.
lokomika
источник
stackoverflow.com/questions/17988756/…
Сиро Сантилли 新疆 改造 中心 法轮功 六四 事件

Ответы:

15

Вот один из способов сделать это:

sed '1,/firstmatch/d;/secondmatch/,$d' 

Объяснено: от первой строки до строки, совпадающей с первым соответствием , удалите. От строки, соответствующей второму совпадению до последней строки, удалите.

Юкка Мателайнен
источник
6

В awk:

awk '
  $1 == "secondmatch" {print_me = 0}
  print_me {print}
  $1 == "firstmatch {print_me = 1}
'
Гленн Джекман
источник
Здесь о скоростях: unix.stackexchange.com/a/194662/16920
Лео Леопольд Херц 준영
Как насчет скорости?
Гленн Джекман
Я думаю, что SED здесь превосходит AWK во времени.
Лео Леопольд Герц 준영
5

Другое sedрешение потерпит неудачу, если firstmatchпроизойдет в 1-й строке 1 .

Проще говоря, используйте один диапазон и пустое регулярное выражение 2 :
либо напечатайте все в этом диапазоне, кроме концов диапазона (автоматическая печать отключена) 3 :

sed -n '/firstmatch/,/secondmatch/{//!p;}' infile

или, короче, удалите все, что не находится в этом диапазоне, а также удалите конец диапазона:

sed '/firstmatch/,/secondmatch/!d;//d' infile


1: Причина в том, что если вторым адресом является регулярное выражение, то проверка на конечное совпадение начнется со строки, следующей за строкой, которая соответствует первому адресу .
Поэтому, /firstmatch/никогда не оценивается для 1-й строки ввода, sedпросто удалит его, так как он соответствует номеру строки в, 1,/RE/и перейдет ко 2-й строке, где он проверяет, соответствует ли строка/firstpattern/

2: Когда REGEX пуст (т.е. //) sedведет себя так, как если бы был указан последний REGEX, использованный в последней примененной команде (либо в качестве адреса, либо в качестве части замещающей команды).

3: ;}синтаксис для современных sedреализаций; с более старыми используйте либо символ новой строки вместо точки с запятой, либо отдельные выражения, напримерsed -n -e '/firstmatch/,/secondmatch/{//!p' -e '}' infile

don_crissti
источник
Можете ли вы объяснить, что //делает (внутри {…})?
G-Man говорит «Восстановить Монику»
Спасибо, но ты попал в мою ловушку. Я знаю, что это //означает последнее использованное регулярное выражение; из всего, что я прочитал, должно быть /secondmatch/. В ходе тестирования я проверил, работает ли ваша команда, и поэтому я пришел к выводу, что она работает как /firstmatch|secondmatch/(что вы подтвердили), но я не могу найти никакой документации (даже документа POSIX, на который вы ссылались, или GNU Руководство пользователя ), которое описывает это поведение. … (Продолжение)
G-Man говорит «Восстановить Монику»
(Продолжение)… Занимательные эксперименты: (I) В sed: (1) Если я это сделаю /first/,4, то //действует как /first/. (2) Если я это сделаю 2,/second/, то //получит ошибку «нет предыдущего регулярного выражения». (Я считаю, что это явный отказ следовать указанному поведению.) (3) Добавление --posixне меняет ничего из вышеперечисленного. (II) В других программах: (4) In vi, после /first/,/second/, //действует как /second/(и другие формы также являются рациональной реализацией документированного правила). … (Продолжение)
G-Man говорит «Восстановить Монику»
(Продолжение)… (5),  awkпохоже, нет понятия «последний использованный RE»; //относится к не символу до или после любого символа. (Я приглашаю вас попробовать echo -- | awk '{ gsub(//, "cha"); print }'.)
G-Man говорит: «Восстановите Монику»
Таким образом, вы читаете «последний REGEX, использованный в последней команде» как «последние REGEX (ы), использованные в последней команде», и поэтому вы (правильно) догадались, что это значит /first|second/. Повезло тебе. Я упоминаю другие программы, чтобы продемонстрировать, что это не какое-то общесистемное соглашение о регулярных выражениях. Кто бы ни добавил это sed, не удосужился добавить это vim, где это имело бы почти такой же смысл. :-) ⁠
G-Man говорит «Восстановить Монику»