Próbuję zbudować wyszukiwanie grep, które wyszukuje termin, ale wyklucza wiersze, które mają drugi termin. Chciałem użyć wielu -e "pattern"
opcji, ale to nie zadziałało.
Oto przykład polecenia, które próbowałem i komunikat o błędzie, który wygenerowałem.
grep -i -E "search term" -ev "exclude term"
grep: exclude term: No such file or directory
Wydaje mi się, że -v
dotyczy wszystkich wyszukiwanych haseł / wzorców. Ponieważ to działa, ale potem nie obejmuje search term
wyników.
grep -i -E "search term" -ve "exclude term"
Odpowiedzi:
Do i wyrażenia z grep potrzebujesz dwóch wywołań:
Jeśli wyszukiwane terminy nie są wyrażeniami regularnymi, użyj ustalonego dopasowania ciągu (
-F
), które jest szybsze:źródło
Poza dwukrotnym wywołaniem grep, jest tylko jeden sposób, aby to osiągnąć. Obejmuje wyrażenia regularne zgodne z Perlem (PCRE) i pewne dość hackerskie stwierdzenia .
Aby wyszukać foo z wyłączeniem dopasowań zawierających pasek , możesz użyć:
Oto jak to działa:
(?!bar)
dopasowuje wszystko, co nie zawiera barów bez konsumowania znaków z łańcucha. Następnie.
zużywa jedną postać.^((?!bar).)*
powtarza powyższe od początku ciągu (^
) do końca ($
). Nie powiedzie się, jeślibar
zostanie napotkany w danym momencie, ponieważ(?!bar)
nie będzie pasował.(?=^((?!bar).)*$)
upewnia się, że łańcuch pasuje do poprzedniego wzorca, bez konsumowania znaków z łańcucha.foo
szuka foo jak zwykle.Znalazłem ten hack w wyrażeniu regularnym, aby dopasować ciąg nie zawierający słowa? . W odpowiedzi Barta Kiersa można znaleźć znacznie bardziej szczegółowe wyjaśnienie działania negatywnego przewidywania.
źródło
Jeśli chcesz to zrobić za jednym razem, możesz użyć awk zamiast grep.
Format:
echo "some text" | awk '/pattern to match/ && !/pattern to exclude/'
Przykłady:
echo "hello there" | awk '/hello/ && !/there/'
Nic nie zwraca.
echo "hello thre" | awk '/hello/ && !/there/'
Zwraca: cześć
echo "hllo there" | awk '/hello/ && !/there/'
Nic nie zwraca.
W przypadku wielu wzorców możesz użyć nawiasów, aby je zgrupować.
Przykłady:
echo "hello thre" | awk '(/hello/ || /hi/) && !/there/'
Zwraca: cześć
echo "hi thre" | awk '(/hello/ || /hi/) && !/there/'
Zwraca: cześć
echo "hello there" | awk '(/hello/ || /hi/) && !/there/'
Nic nie zwraca.
echo "hi there" | awk '(/hello/ || /hi/) && !/there/'
Nic nie zwraca.
źródło
ls --color=always | awk '/hello/ && !/goodbye/'
grep -R
w kilku plikach kodu za pomocą wiersza poleceń Ubuntu.Z moich eksperymentów nie ma większego znaczenia, jeśli wprowadzisz warunki wykluczenia przez
grep
lubsed
. Sed ma kilka innych przydatnych funkcji zastępowania tekstu, których często używam do lepszego filtrowania plików dziennika. Więc użyję sed, ponieważ łączę sporo filtrów na sed.źródło
grep -F
zamiastgrep -E
i nie używaj go,-i
jeśli go nie potrzebujesz.sed
;)