A e espressioni con grep hai bisogno di due invocazioni:
grep -Ei "search term" | grep -Eiv "exclude term"
Se i termini che stai cercando non sono espressioni regolari, utilizza la corrispondenza di stringhe fissa (-F
) che è più veloce:
grep -F "search term" | grep -Fv "exclude term"
A parte l'invocazione di grep due volte, c'è solo un modo a cui riesco a pensare per ottenere questo risultato. Coinvolge Perl Compatible Regular Expressions (PCRE) e alcune asserzioni piuttosto confuse.
Per cercare foo escludendo le corrispondenze che contengono barra , puoi utilizzare:
grep -P '(?=^((?!bar).)*$)foo'
Ecco come funziona:
-
(?!bar)
corrisponde a tutto ciò che non barra senza consumare caratteri dalla stringa. Poi.
consuma un solo carattere. -
^((?!bar).)*
ripete quanto sopra dall'inizio della stringa (^
) fino alla fine ($
). Fallirà sebar
si incontra in un dato punto, a partire da(?!bar)
non corrisponderà. -
(?=^((?!bar).)*$)
assicura che la stringa corrisponda al modello precedente, senza consumare caratteri dalla stringa. -
foo
cerca foo come al solito.
Ho trovato questo trucco in Espressione regolare per abbinare la stringa che non contiene una parola?. Nella risposta di Bart Kiers, puoi trovare una spiegazione molto più dettagliata di come funziona la previsione negativa.
Se vuoi farlo in un solo passaggio, puoi usare awk invece di grep.
Formato:
echo "some text" | awk '/pattern to match/ && !/pattern to exclude/'
Esempi:
echo "hello there" | awk '/hello/ && !/there/'
Non restituisce nulla.
echo "hello thre" | awk '/hello/ && !/there/'
Restituisce:ciao tre
echo "hllo there" | awk '/hello/ && !/there/'
Non restituisce nulla.
Per più modelli, puoi utilizzare le parentesi per raggrupparli.
Esempi:
echo "hello thre" | awk '(/hello/ || /hi/) && !/there/'
Restituisce:ciao tre
echo "hi thre" | awk '(/hello/ || /hi/) && !/there/'
Restituisce:ciao tre
echo "hello there" | awk '(/hello/ || /hi/) && !/there/'
Non restituisce nulla.
echo "hi there" | awk '(/hello/ || /hi/) && !/there/'
Non restituisce nulla.