Za pomocą awk
lub sed
jak mogę wybrać linie, które występują między dwoma różnymi wzorami znaczników? Może być wiele sekcji oznaczonych tymi wzorami.
Na przykład: załóżmy, że plik zawiera:
abc
def1
ghi1
jkl1
mno
abc
def2
ghi2
jkl2
mno
pqr
stu
Wzorzec początkowy to, abc
a wzór końcowy to mno
Więc potrzebuję wyniku jako:
def1
ghi1
jkl1
def2
ghi2
jkl2
Używam seda do dopasowania wzorca raz:
sed -e '1,/abc/d' -e '/mno/,$d' <FILE>
Czy istnieje jakiś sposób sed
czy awk
to zrobić, aż do końca pliku?
awk '/abc/{a=1}/mno/{print;a=0}a' file
.awk '/abc/{a=1} a; /mno/{a=0}' file
- z tym, umieszczająca
warunek przed parametrem,/mno/
sprawimy, że oceni wiersz jako prawdziwy (i wydrukujemy go) przed ustawieniema=0
. W ten sposób możemy uniknąć pisaniaprint
.awk '/abc/,/mno/' file
awk '/abc/{flag=1}/mno/{flag=0}flag' file
powinien zrobić.awk 'flag; /PAT1/{flag=1; next} /PAT1/{flag=0}' file
zrobi.Używając
sed
:Te
-n
środki nie są drukowane opcja domyślnie.Wzorzec szuka wierszy zawierających tylko
abc
to justmno
, a następnie wykonuje akcje w{ ... }
. Pierwsza akcja usuwaabc
wiersz; drugamno
linia; ap
drukuje pozostałe wiersze. W razie potrzeby możesz rozluźnić wyrażenia regularne. Żadne wiersze spoza zakresuabc
...mno
po prostu nie są drukowane.źródło
-e
sed
powinien zostać wykonany. Jeśli chcesz lub potrzebujesz użyć kilku argumentów, aby uwzględnić cały skrypt, musisz użyć ich-e
przed każdym takim argumentem; w przeciwnym razie jest opcjonalne (ale jawne).d
do wszystkich linii do pierwszego dopasowania, a następnied
do wszystkich linii zaczynających się od drugiego dopasowania?To może zadziałać dla Ciebie (GNU sed):
Usuń wszystkie wiersze oprócz tych między wierszami rozpoczynającymi się
abc
imno
źródło
!d;//d
golfi 2 znaki lepiej :-) stackoverflow.com/a/31380266/895245{//!b}
zapobiegaabc
imno
od włączenia do wyjścia, ale nie mogę dowiedzieć się, jak to zrobić. Czy możesz wytłumaczyć?//!b
czyta, jeśli bieżąca linia nie jest jedną z linii, które pasują do zakresu, przerwij i dlatego wypisz te linie, w przeciwnym razie wszystkie inne linie zostaną usunięte.gra o dwie postacie lepiej niż ppotong
{//!b};d
Puste ukośniki
//
oznaczają: „użyj ponownie ostatniego użytego wyrażenia regularnego”. a polecenie robi to samo, co bardziej zrozumiałe:To wydaje się być POSIX :
źródło
Z linków z poprzedniej odpowiedzi wynika, że ten, który zrobił to dla mnie, działając
ksh
na Solarisie, był taki:1,/firstmatch/d
: od linii 1 do pierwszego znalezieniafirstmatch
, usuń./secondmatch/,$d
: od pierwszego wystąpieniasecondmatch
do końca pliku, usuń.źródło
1,
) występuje wcześniej/firstmatch/
? Zgaduję, że można to również wyrazić'/firstmatch/1,d;/secondmatch,$d'
?źródło
coś takiego działa u mnie:
file.awk:
za pomocą:
awk -f file.awk data
...edit: O_o fedorqui rozwiązanie jest o wiele lepsze / ładniejsze niż moje.
źródło
if (record=1)
powinno byćif (record==1)
, tj. Podwójne=
- patrz operatory porównania gawkOdpowiedź Don_crissti z Pokaż tylko tekst między 2 pasującymi wzorami ?
który jest znacznie bardziej wydajny niż aplikacja AWK, patrz tutaj .
źródło
Próbowałem użyć
awk
do wydrukowania linii między dwoma wzorami, podczas gdy wzorzec 2 również pasuje do wzorca 1 . Należy również wydrukować linię pattern1.np. źródło
powinien mieć ouput
Gdzie
package BBB
wzorzec1 jest, tam wzorzec2package \w*
. Zauważ, żeCCC
nie jest to znana wartość, więc nie można jej dosłownie dopasować.W tym przypadku ani @scai, ani @fedorqui
awk '/abc/{a=1}/mno/{print;a=0}a' file
nieawk '/abc/{a=1} a; /mno/{a=0}' file
działają dla mnie.W końcu udało mi się to rozwiązać
awk '/package BBB/{flag=1;print;next}/package \w*/{flag=0}flag' file
, hahaTrochę więcej wysiłku powoduje
awk '/package BBB/{flag=1;print;next}flag;/package \w*/{flag=0}' file
wydrukowanie również linii wzorca2, to znaczyźródło