Drukuj linie między (i wykluczając) dwa wzory

13

Zamierzam przesłać formularz za pomocą cURL, gdzie część zawartości pochodzi z innego pliku, wybranego za pomocą sed

Jeśli param1używa wzorca do dopasowywania linii z innego pliku sed, poniższe polecenie będzie działać poprawnie:

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

Teraz przejdź do problemu. Chcę pokazać tylko tekst między 2 pasującymi wzorami, z wyjątkiem samego pasującego wzoru.

Powiedzmy, że file.txtzawiera:

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.

Obecnie wiele sedpoleceń „między 2 pasującymi wzorami” nie usuwa firstmatchi secondmatch.

Chcę, aby wynik stał się:

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
źródło
stackoverflow.com/questions/17988756/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Odpowiedzi:

15

Oto jeden ze sposobów, w jaki możesz to zrobić:

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

Objaśnienie: Od pierwszej linii do linii pasującej do pierwszego dopasowania usuń. Od linii dopasowującej secondmatch do ostatniej linii usuń.

Jukka Matilainen
źródło
6

W awk:

awk '
  $1 == "secondmatch" {print_me = 0}
  print_me {print}
  $1 == "firstmatch {print_me = 1}
'
Glenn Jackman
źródło
Tutaj o prędkościach: unix.stackexchange.com/a/194662/16920
Léo Léopold Hertz 준영
Co z prędkościami?
glenn jackman
Myślę, że SED jest lepszy w porównaniu do AWK w czasie.
Léo Léopold Hertz -
5

Inne sedrozwiązanie zawiedzie, jeśli firstmatchwystąpi w 1. linii 1 .

Uprość to, użyj jednego zakresu i pustego 2 wyrażenia regularnego:
wydrukuj wszystko w tym zakresie z wyłączeniem końców zakresu (automatyczne drukowanie wyłączone) 3 :

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

lub, krócej, usuń wszystko spoza tego zakresu, a także usuń końce zakresu:

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


1: Powodem jest to, że jeśli drugi adres jest wyrażeniem regularnym, wówczas sprawdzanie dopasowania końcowego rozpocznie się od wiersza następującego po wierszu, który pasował do pierwszego adresu .
Dlatego /firstmatch/nigdy nie jest oceniany dla pierwszego wiersza wejścia, sedpo prostu go usunie, ponieważ pasuje do numeru wiersza, 1,/RE/i przejdzie do drugiego wiersza, w którym sprawdza, czy wiersz pasuje/firstpattern/

2: Gdy REGEX jest pusty (tj. //) sedZachowuje się tak, jakby podano ostatni REGEX użyty w ostatnim zastosowanym poleceniu (jako adres lub jako część polecenia zastępczego).

3: ;}składnia dotyczy nowoczesnych sedimplementacji; ze starszymi użyj albo nowej linii zamiast średnika, albo oddzielnych wyrażeń, npsed -n -e '/firstmatch/,/secondmatch/{//!p' -e '}' infile

don_crissti
źródło
Czy możesz wyjaśnić, co //się dzieje (w środku {…})?
G-Man mówi „Przywróć Monikę”
Dzięki, ale wpadłeś w moją pułapkę. Wiem, że //oznacza to ostatnie użyte wyrażenie regularne; ze wszystkiego, co przeczytałem, powinno być /secondmatch/. Sprawdziłem, czy twoje polecenie działa, więc doszedłem do wniosku, że działa on tak jak /firstmatch|secondmatch/(co potwierdziłeś), ale nie mogę znaleźć żadnej dokumentacji (nawet dokumentu POSIX, z którym się łączyłeś, ani GNU sed manual ), który opisuje to zachowanie. … (Ciąg dalszy)
G-Man mówi „Przywróć Monikę”
(Ciąg dalszy)… Zabawne eksperymenty: (I) W sed: (1) Jeśli tak /first/,4, to //zachowuje się jak /first/. (2) Jeśli tak 2,/second/, //pojawia się błąd „brak poprzedniego wyrażenia regularnego”. (Uważam to za rażące zaniechanie podanego zachowania.) (3) Dodanie --posixnie zmienia żadnego z powyższych. (II) W innych programach: (4) W vi, po /first/,/second/, //działa jak /second/(a inne formy są racjonalnymi implementacjami udokumentowanej reguły). … (Ciąg dalszy)
G-Man mówi „Przywróć Monikę”
(Ciąg dalszy)… (5)  awkwydaje się nie mieć pojęcia „ostatnio użyty składnik RE”; //odnosi się do nie-znaku przed lub po dowolnym znaku. (Zapraszam do spróbowania echo -- | awk '{ gsub(//, "cha"); print }'.)
G-Man mówi „Przywróć Monikę”
Czytasz więc „ostatni REGEX użyty w ostatnim poleceniu” jako „ostatni REGEX (y) użyty w ostatnim poleceniu”, więc (poprawnie) zgadłeś, że to znaczy /first|second/. Szczęściarz. Wspominam o innych programach, aby wykazać, że nie jest to jakaś ogólna systemowa konwencja wyrażeń regularnych. Ktokolwiek go dodał, sednie zawracał sobie głowy dodawaniem go vim, gdzie miałoby to tyle samo sensu. :-) ⁠
G-Man mówi „Przywróć Monikę”