Próbuję użyć, grep
aby wyświetlić tylko wiersze zawierające jedno z dwóch słów, jeśli tylko jedno z nich pojawia się w wierszu, ale nie, jeśli znajdują się w tym samym wierszu.
Do tej pory próbowałem, grep pattern1 | grep pattern2 | ...
ale nie uzyskałem oczekiwanego rezultatu.
[a-z][a-z0-9]\(,7\}\(\.[a-z0-9]\{,3\}\)+
? (2) Co się stanie, jeśli jedno ze słów / wzorów pojawi się więcej niż jeden raz w linii (a drugie nie pojawi się)? Czy jest to równoważne słowu występującemu raz, czy też liczy się jako wielokrotne wystąpienie?Odpowiedzi:
Narzędzie inne niż
grep
jest do zrobienia.Na przykład, używając perla, komenda wyglądałaby następująco:
perl -ne
uruchamia polecenie podane dla każdej linii standardowej, która w tym przypadku wypisuje linię, jeśli pasuje/pattern1/ xor /pattern2/
, lub innymi słowy dopasowuje jeden wzór, ale nie drugi (wyłączny lub).Działa to dla wzorca w dowolnej kolejności i powinno mieć lepszą wydajność niż wiele wywołań
grep
, a także mniej pisania.Lub, nawet krócej, z awk:
lub dla wersji awk, które nie mają
xor
:źródło
xor
dostępny tylko w GNU Awk?/pattern1/+/pattern2/==1
irxor
.\b
) w samych wzorcach, tj\bword\b
.Dzięki GNU
grep
możesz przekazać oba słowa do,grep
a następnie usunąć linie zawierające oba wzorce.źródło
Spróbuj z
egrep
źródło
grep -e foo -e bar | grep -v -e 'foo.*bar' -e 'bar.*foo'
Direct invocation as either egrep or fgrep is deprecated
- preferujgrep -E
-f
i-e
opcje, chociaż są starszeegrep
ifgrep
będą przez jakiś czas obsługiwane.grep
(to podpory-F
,-E
,-e
,-f
jak tego wymaga POSIX) jest/usr/xpg4/bin
. Narzędzia w/bin
są przestarzałe.Dzięki
grep
implementacjom, które obsługują wyrażenia regularne podobne do perla (jakpcregrep
lub GNU lub ast-opengrep -P
), możesz to zrobić za pomocą jednegogrep
wywołania za pomocą:To jest znaleźć linie, które pasują,
pat1
ale niepat2
,pat2
ale niepat1
.(?=...)
i(?!...)
są odpowiednio operatorami perspektywicznymi i negatywnymi. Tak więc technicznie powyższe wygląda na początek tematu (^
) pod warunkiem, że następuje po nim.*pat1
i nie następuje po nim.*pat2
, lub to samo zpat1
ipat2
odwrócone.Jest to nieoptymalne dla linii zawierających oba wzorce, ponieważ byłyby wówczas dwukrotnie wyszukiwane. Zamiast tego możesz użyć bardziej zaawansowanych operatorów perla, takich jak:
(?(1)yespattern|nopattern)
pasuje do,yespattern
jeśli grupa przechwytywania1
st (pusta()
powyżej) jest zgodna, inopattern
inaczej. Jeśli to()
mecze, że środkipat1
nie są zgodne, więc szukamypat2
(pozytywnego spojrzenia w przyszłość) i patrzymy na niepat2
inaczej (negatywny patrzeć w przyszłość).Za pomocą
sed
możesz to napisać:źródło
grep: the -P option only supports a single pattern
, przynajmniej na każdym systemie, do którego mam dostęp. +1 za drugie rozwiązanie.grep
.pcregrep
a ast-open grep nie ma tego problemu. Zamieniłem wielokrotność-e
na alternatywny operator RE, więc powinien on działać również z GNUgrep
.Mówiąc logicznie, szukasz A xor B, który można zapisać jako
(A i nie B)
lub
(B i nie A)
Biorąc pod uwagę, że twoje pytanie nie wspomina, że zajmujesz się kolejnością danych wyjściowych, o ile wyświetlane są pasujące linie, rozszerzenie boolowskie A xor B jest dość proste w grep:
źródło
sort | uniq
.Dla następującego przykładu:
Można to zrobić wyłącznie z
grep -E
,uniq
, iwc
.Jeśli
grep
jest skompilowany z wyrażeniami regularnymi Perla, możesz dopasować do ostatniego wystąpienia, zamiast konieczności potoku douniq
:Wynik:
Jednowarstwowy:
Jeśli nie chcesz na stałe kodować wzorca, składanie go ze zmiennym zestawem elementów można zautomatyzować za pomocą funkcji.
Można to również zrobić natywnie w Bash jako funkcję bez rur lub dodatkowych procesów, ale byłby bardziej zaangażowany i prawdopodobnie nie wchodzi w zakres twojego pytania.
źródło
Big apple\n
ipear-shaped\n
, następnie wyjście powinno zawierać zarówno tych linii. Twoje rozwiązanie uzyskałoby liczbę 2; w długiej wersji będzie napisane „Dopasowane oba słowa” (co jest odpowiedzią na złe pytanie), a w krótkiej wersji nic nie powie. (3) Sugestia: użycie-o
tutaj jest naprawdę złym pomysłem, ponieważ ukrywa wiersze zawierające dopasowania, więc nie możesz zobaczyć, kiedy oba słowa pojawiają się w tym samym wierszu. … (Ciąg dalszy)uniq
/sort -u
i fantazyjnego wyrażenia regularnego Perla, by dopasować tylko ostatnie wystąpienie w każdym wierszu, tak naprawdę nie stanowi użytecznej odpowiedzi na to pytanie. Ale nawet gdyby tak było, nadal byłaby to zła odpowiedź, ponieważ nie wyjaśnisz, w jaki sposób przyczyniają się do udzielenia odpowiedzi na pytanie. (Zobacz odpowiedź Stéphane'a Chazelasa na przykład dobrego wyjaśnienia.)