Nie próbuj do tego używać grep, zamiast tego użyj awk. Aby dopasować 2 wyrażenia regularne R1 i R2 w grep, można by pomyśleć, że będzie to:
grep 'R1.*R2|R2.*R1'
w awk będzie to:
awk '/R1/ && /R2/'
ale co jeśli R2
nakłada się na podzbiór lub jest jego podzbiorem R1
? To polecenie grep po prostu nie zadziałałoby, podczas gdy polecenie awk. Powiedzmy, że chcesz znaleźć wiersze zawierające the
i heat
:
$ echo 'theatre' | grep 'the.*heat|heat.*the'
$ echo 'theatre' | awk '/the/ && /heat/'
theatre
Musisz do tego użyć 2 grepsa i fajki:
$ echo 'theatre' | grep 'the' | grep 'heat'
theatre
i oczywiście, jeśli rzeczywiście wymagałeś ich oddzielności, zawsze możesz napisać w awk ten sam wyrażenie regularne, którego używałeś w grep, i istnieją alternatywne rozwiązania awk, które nie wymagają powtarzania wyrażeń regularnych w każdej możliwej sekwencji.
Odkładając to na bok, co jeśli chcesz rozszerzyć swoje rozwiązanie, aby pasowało do 3 wyrażeń regularnych R1, R2 i R3. W grep byłby to jeden z tych złych wyborów:
grep 'R1.*R2.*R3|R1.*R3.*R2|R2.*R1.*R3|R2.*R3.*R1|R3.*R1.*R2|R3.*R2.*R1' file
grep R1 file | grep R2 | grep R3
podczas gdy w awk byłoby zwięzłe, oczywiste, proste, wydajne:
awk '/R1/ && /R2/ && /R3/'
A jeśli teraz chcesz dopasować dosłowne ciągi znaków S1 i S2 zamiast wyrażeń regularnych R1 i R2? Po prostu nie możesz tego zrobić w jednym wywołaniu grep, musisz albo napisać kod, aby uciec od wszystkich metazarów RE przed wywołaniem grep:
S1=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< 'R1')
S2=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< 'R2')
grep 'S1.*S2|S2.*S1'
lub ponownie użyj 2 greps i fajki:
grep -F 'S1' file | grep -F 'S2'
które znowu są złymi wyborami, podczas gdy w awk po prostu używasz operatora łańcuchowego zamiast operatora wyrażenia regularnego:
awk 'index($0,S1) && index($0.S2)'
Co teraz, jeśli chcesz dopasować 2 wyrażenia regularne w akapicie zamiast w wierszu? Nie można tego zrobić w grep, trywialny w awk:
awk -v RS='' '/R1/ && /R2/'
Co powiesz na cały plik? Znowu nie można tego zrobić w grep i trywialnym w awk (tym razem używam GNU awk dla wieloznakowego RS dla zwięzłości, ale nie jest to dużo więcej kodu w żadnym awk lub możesz wybrać znak kontrolny, o którym wiesz, że nie będzie być na wejściu, aby RS zrobił to samo):
awk -v RS='^$' '/R1/ && /R2/'
Więc - jeśli chcesz znaleźć wiele wyrażeń regularnych lub ciągów w linii, akapicie lub pliku, nie używaj grep, użyj awk.