Staram się grepować we wszystkich przypadkach, w których Ui\.
nie następuje po Line
prostu literaL
Jaki jest właściwy sposób zapisania wyrażenia regularnego, aby znaleźć wszystkie wystąpienia określonego ciągu, a po nich NIE następuje inny ciąg?
Korzystanie z lookaheads
grep "Ui\.(?!L)" *
bash: !L: event not found
grep "Ui\.(?!(Line))" *
nothing
regex
grep
regex-lookarounds
Lee Quarella
źródło
źródło
set +o histexpand
w Bash lubset +H
YMMV.Odpowiedzi:
Negatywne spojrzenie w przód, którego szukasz, wymaga potężniejszego narzędzia niż standardowe
grep
. Potrzebujesz grepa z obsługą PCRE.Jeśli masz GNU
grep
, aktualna wersja obsługuje opcje-P
lub--perl-regexp
i możesz wtedy użyć żądanego wyrażenia regularnego.Jeśli nie masz (wystarczająco aktualnej wersji) GNU
grep
, rozważ możliwość pobraniaack
.źródło
!
jako znak specjalny.-P
nie jest to obsługiwane, spróbuj ponownie uzyskać wynik potokowaniagrep --invert-match
, npgit log --diff-filter=D --summary | grep -E 'delete.*? src' | grep -E --invert-match 'xml'
. : . Pamiętaj, aby zagłosować za odpowiedzią @Vinicius Ottoni.Odpowiedź na część twojego problemu jest tutaj, a potwierdzenie zachowałoby się w ten sam sposób: Potwierdzenie i negatywne spojrzenie w przód z błędami
Używasz podwójnych cudzysłowów dla grep, co pozwala bashowi "interpretować
!
jako polecenie rozszerzania historii".Musisz zawinąć swój wzór w POJEDYNCZE CYTATY:
grep 'Ui\.(?!L)' *
Jednak zobacz odpowiedź @ JonathanLeffler, aby rozwiązać problemy z negatywnym wyprzedzeniem w standardzie
grep
!źródło
grep
z funkcjonalnością standardugrep
, gdzie standardem dlagrep
jest POSIX. To, co mówisz, jest również prawdą - uruchamiam Bash z wyłączonym barbarzyństwem powłoki C (bo gdybym chciał powłoki C, użyłbym jednej, ale nie chcę), więc!
to nie wpływa na mnie - ale aby uzyskać negatywne wyprzedzenia, potrzebujesz niestandardowychgrep
.Prawdopodobnie nie możesz wykonać standardowego negatywnego lookahead używając grep, ale zwykle powinieneś być w stanie uzyskać równoważne zachowanie używając "odwrotnego" przełącznika '-v'. Korzystając z tego, możesz skonstruować wyrażenie regularne jako uzupełnienie tego, co chcesz dopasować, a następnie przepuścić je przez 2 greps.
W przypadku danego wyrażenia regularnego możesz zrobić coś takiego jak
źródło
Jeśli potrzebujesz implementacji wyrażenia regularnego, która nie obsługuje ujemnych lookaheadów i nie masz nic przeciwko dopasowaniu dodatkowych znaków *, możesz użyć zanegowanych klas znaków
[^L]
, alternacji|
i zakotwiczenia końca łańcucha$
.W twoim przypadku
grep 'Ui\.\([^L]\|$\)' *
spełnia swoje zadanie.Ui\.
pasuje do ciągu, który Cię interesuje\([^L]\|$\)
dopasowuje dowolny pojedynczy znak inny niżL
lub pasuje do końca wiersza:[^L]
lub$
.Jeśli chcesz wykluczyć więcej niż jeden znak, wystarczy rzucić na niego więcej zmian i negacji. Aby znaleźć
a
nie następujebc
:grep 'a\(\([^b]\|$\)\|\(b\([^c]\|$\)\)\)' *
Który jest albo (
a
po którym następuje notb
lub koniec wiersza:a
then[^b]
lub$
) albo (a
pob
którym następuje albo nie,c
albo koniec wiersza:a
thenb
, then[^c]
lub$
.Tego rodzaju wyrażenie staje się dość nieporęczne i podatne na błędy nawet przy krótkim ciągu. Mógłbyś napisać coś, co wygeneruje dla ciebie wyrażenia, ale prawdopodobnie byłoby łatwiej po prostu użyć implementacji regex, która obsługuje negatywne lookaheads.
* Jeśli Twoja implementacja obsługuje grupy bez przechwytywania , możesz uniknąć przechwytywania dodatkowych znaków.
źródło
Jeśli twój grep nie obsługuje -P lub --perl-regexp i możesz zainstalować grep z obsługą PCRE, np. "Pcregrep", to nie będzie potrzebował żadnych opcji wiersza poleceń, takich jak GNU grep, aby zaakceptować zwykły zgodny z Perl wyrażenia, po prostu uciekasz
Nie potrzebujesz kolejnej grupy zagnieżdżonej dla „Linii”, jak w Twoim przykładzie „Ui. (?! (Linia))” - zewnętrzna grupa jest wystarczająca, jak pokazałem powyżej.
Pozwólcie, że podam inny przykład szukania negatywnych twierdzeń: kiedy masz listę wierszy, zwracaną przez "ipset", każda linia pokazuje liczbę pakietów w środku linii i nie potrzebujesz linii z zerowymi pakietami, po prostu biegać:
Jeśli lubisz wyrażenia regularne kompatybilne z perlem i masz perl, ale nie masz programu pcregrep lub twój grep nie obsługuje --perl-regexp, możesz użyć jednowierszowych skryptów perl, które działają tak samo jak grep:
Perl akceptuje stdin w taki sam sposób jak grep, np
źródło