W grep, w jaki sposób mogę dopasować wzór i odwrócić dopasować inny wzór?


11

Za pomocą grepchcę wybrać wszystkie linie, które pasują do wzoru i które nie pasują do innego wzoru. Chcę móc użyć pojedynczego wywołania, grepaby móc skorzystać z --after-contextopcji (lub --before-context, lub --context).

-vnie jest tutaj wykonalne, ponieważ neguje wszystkie wzorce, które przekazuję grepprzy użyciu -eopcji.

Przykład

Chcę szukać pasujących linii needle, ignorując pasujące linie ignore me, z jedną linią następującego kontekstu.

Oto mój plik wejściowy:

one needle ignore me
two
three
four needle
five

Dane wyjściowe, których chcę, to:

four needle
five

Jak widać, to naiwne rozwiązanie nie działa:

$ cat file | grep --after-context=1 needle | grep -v 'ignore me'
two
---
four needle
five

Odpowiedzi:



8

Wygląda na to, że używasz GNU . Z GNU grep możesz przekazać --perl-regexflagę, aby aktywować PCRE, a następnie podać negatywne stwierdzenie dotyczące przyszłości, przykład poniżej

grep --after-context=1 \
--perl-regex '^(?:(?!ignore me).)*needle(?:(?!ignore me).)*$' file.txt
four needle
five

Najważniejsze w tym miejscu jest (?:(?!STRING).)*to, STRINGco [^CHAR]*jestCHAR


@ 1_CR ... Sir .. to jest niesamowite ..: P coś do smileraack
Rahul Patil

@RahulPatil. :-), tak GNU grep jest tak dobry.
iruvar

Nie do końca tego chcę. Chcę, żeby zadziałało, czy „ignoruj ​​mnie” występuje przed czy po „igle”.
Flimm

@RahulPatil, dzięki, naprawiłem to w najnowszej wersji
iruvar,

Bardzo przydatne. Zwłaszcza w przypadku grep z kontekstem, w którym chcesz wykluczyć ściśle pasujące linie, ale bez pewnej części wzoru. Blisko pierwotnego pytania, ale nie do końca takie samo.
Gaoithe

2

Sugerowałbym użycie zamiast tego awk, ponieważ lepiej obsługuje on wieloliniowe operacje we / wy. Albo 1) Prześlij wyniki do GNU awk --\nza pomocą separatora rekordów, lub 2) Wykonaj całe dopasowanie w awk.

opcja 1

<file grep -A1 needle | awk '!/ignore me/' RS='--\n' ORS='--\n'

Wynik:

four needle                                                                                  
five
--

Uwaga: ta opcja przeszukuje cały rekord ignore me, ustawia FS=1i dopasowuje, $1aby porównać tylko z pierwszym wierszem.

Opcja 2

<file awk 'a-- > 0; $0 ~ re1 && $0 !~ re2 { print $0; a=after }' re1=needle re2='ignore me' after=1

Czy ignore mew pliku jest wiele , awk nie działa
Rahul Patil

@RahulPatil: czy mógłbyś przeformułować lub dodać więcej szczegółów do swojego pytania? Nie rozumiem o co pytasz.
Thor,

@Thos przetestuj swój przykład za pomocą tego pliku wejściowego paste.ubuntu.com/6252860
Rahul Patil

@RahulPatil: Rozumiem, co masz na myśli, opcja 1 zakłada, że --\nmiędzy każdą dopasowaną grupą znajduje się separator, którego nie ma, jeśli grupy sąsiadują ze sobą. Sposób obsługi sąsiednich grup jest zależny od zadania, więc niekoniecznie jest to złe. Opcja 2 nie zależy od separatora i nie ma na nią wpływu.
Thor,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.