Vorrei ottenere la corrispondenza multi pattern con AND tra i modelli, vale a dire equivalente allesecuzione di diversi greps in una sequenza:
grep pattern1 | grep pattern2 | ...
Quindi come convertirlo in qualcosa di simile?
grep pattern1 & pattern2 & pattern3
Vorrei usare un singolo grep perché sto costruendo argomenti dinamicamente, quindi tutto deve stare in una stringa. Luso del filtro è una funzionalità di sistema, non grep, quindi non è un argomento per esso.
Non confondere questa domanda con:
grep "pattern1\|pattern2\|..."
Questa è una OR corrispondenza di più pattern.
Commenti
Risposta
agrep
può farlo con questa sintassi:
agrep "pattern1;pattern2"
Con GNU grep
, quando viene creato w ith supporto PCRE, puoi fare:
grep -P "^(?=.*pattern1)(?=.*pattern2)"
Con ast grep
:
grep -X ".*pattern1.*&.*pattern2.*"
(aggiunta di .*
s come <x>&<y>
trova stringhe che corrispondono sia a <x>
che a <y>
esattamente , a&b
non corrisponderebbe mai in quanto” non esiste alcuna stringa di questo tipo che può essere sia a
che b
allo stesso tempo).
Se i pattern non si sovrappongono, potresti anche essere in grado di:
grep -e "pattern1.*pattern2" -e "pattern2.*pattern1"
Il miglior modo portatile è probabilmente con awk
come già accennato:
awk "/pattern1/ && /pattern2/"
Con sed
:
sed -e "/pattern1/!d" -e "/pattern2/!d"
Tieni presente che tutti avranno una sintassi delle espressioni regolari diversa.
Commenti
- La sintassi
agrep
non funziona per io … in quale versione era stato introdotto? - @Raman 2.04 del 1992 lo aveva già. ‘ non ho motivo di credere che ‘ non fosse presente fin dallinizio. Le versioni più recenti (dopo il 1992) di
agrep
possono essere trovate incluse in glimpse / webglimpse . Forse hai unimplementazione diversa. Tuttavia, ho commesso un errore con la versione ast-grep, lopzione per espressioni regolari aumentate è-X
, non-A
. - @St é phaneChazelas Grazie, ho
agrep
0.8.0 su Fedora 23. Sembra essere unagrep
diverso da quello a cui fai riferimento. - @Raman, il tuo suona come TRE
agrep
. - @Techiee, o semplicemente
awk '/p1/ && /p2/ {n++}; END {print 0+n}'
Risposta
Non hai specificato la versione di grep, questo è importante. Alcuni motori regexp consentono più corrispondenze raggruppate da AND utilizzando “& “ma questa non è una funzionalità standard e non portabile. Ma almeno GNU grep non lo supporta.
OTOH puoi semplicemente sostituire grep con sed, awk, perl, ecc. . (elencati in ordine di peso crescente). Con awk, il comando sarebbe
awk "/regexp1/ && /regexp2/ && /regexp3/ { print; }"
e può essere costruito per essere specificato nella riga di comando in modo semplice.
Commenti
- Ricorda solo che
awk
utilizza ERE ‘, ad es. lequivalente digrep -E
, in contrasto con i BRE ‘ utilizzati dagrep
. -
awk
‘ Le espressioni regolari sono chiamate ERE, ma in realtà ‘ sono un po idiosincratico. Probabilmente qui ci sono più dettagli di quanto chiunque voglia: wiki.alpinelinux.org/wiki/Regex - Grazie, grep 2.7.3 ( openSUSE). Ti ho votato positivamente, ma terrò la domanda aperta per un po , forse cè qualche trucco per grep (non che non mi piaccia
awk
– semplicemente sapere di più è meglio). - Lazione predefinita è stampare la riga corrispondente in modo che la parte
{ print; }
non sia ‘ in realtà qui necessaria o utile.
Risposta
Se patterns
contiene un pattern per riga, puoi fare qualcosa del genere:
awk "NR==FNR{a[$0];next}{for(i in a)if($0!~i)next}1" patterns -
Oppure questo corrisponde a sottostringhe invece di regolare espressioni:
awk "NR==FNR{a[$0];next}{for(i in a)if(!index($0,i))next}1" patterns -
Per stampare tutto invece di nessuna riga dellinput nel se patterns
è vuoto, sostituisci NR==FNR
con FILENAME==ARGV[1]
o con ARGIND==1
in gawk
.
Queste funzioni stampano le righe di STDIN che contengono ogni stringa specificata come argomento come sottostringa. ga
sta per grep all e gai
ignora maiuscole e minuscole.
ga(){ awk "FILENAME==ARGV[1]{a[$0];next}{for(i in a)if(!index($0,i))next}1" <(printf %s\\n "$@") -; } gai(){ awk "FILENAME==ARGV[1]{a[tolower($0)];next}{for(i in a)if(!index(tolower($0),i))next}1" <(printf %s\\n "$@") -; }
Commenti
- risposta chiara che affronta diversi casi duso e lavori (verificato su macos)
Risposta
grep pattern1 | grep pattern2 | ...
Vorrei usare un singolo grep perché sto costruendo argomenti dinamicamente , quindi tutto deve stare in una stringa
È effettivamente possibile costruire la pipeline in modo dinamico (senza ricorrere a eval
):
# Executes: grep "$1" | grep "$2" | grep "$3" | ... function chained-grep { local pattern="$1" if [[ -z "$pattern" ]]; then cat return fi shift grep -- "$pattern" | chained-grep "$@" } cat something | chained-grep all patterns must match order but matter dont
Tuttavia, probabilmente non è una soluzione molto efficiente.
Commenti
- Utilizza
chained-grep()
ofunction chained-grep
ma nonfunction chained-grep()
: unix.stackexchange.com/questions/73750/… - Puoi descrivere qual è il trucco? Puoi aggiungerlo alla risposta ( senza ” Modifica: “, ” Aggiornare: ” o simile) modificandolo ?
- Riformulata la risposta per rendere più chiaro il trucco (es .: costruire dinamicamente una shell pipeline)
Risposta
git grep
Ecco la sintassi utilizzando git grep
combinazione di più pattern utilizzando espressioni booleane :
git grep --no-index -e pattern1 --and -e pattern2 --and -e pattern3
Il comando precedente stamperà le righe che corrispondono a tutti i modelli contemporaneamente.
--no-index
Cerca i file nella directory corrente che non è gestita da Git.
Seleziona man git-grep
per assistenza.
Vedi anche:
- Come contattarci e grep per trovare string1 AND string2?
- Controlla se tutte le stringhe multiple o regex esistono in un file .
Per loperazione OR , vedere:
- Come posso grep per più pattern con pattern con carattere pipe?
- Grep: come aggiungere un ” OPPURE ” condition?
Commenti
- Ottima risposta. Grazie.
Risposta
Ecco la mia opinione, e funziona per parole su più righe:
Utilizza find . -type f
seguito da altrettanti
-exec grep -q "first_word" {} \;
e lultima parola chiave con
-exec grep -l "nth_word" {} \;
-q
silenzioso / silenzioso
-l
mostra file con corrispondenze
Il seguente elenco di nomi di file contenente le parole “coniglio” e “buco”:
find . -type f -exec grep -q "rabbit" {} \; -exec grep -l "hole" {} \;
Commenti
- Se guardi attentamente, potresti apprendere che questa non è la funzionalità richiesta dalla domanda.
Risposta
ripgrep
Ecco lesempio che utilizza rg
:
rg -N "(?P<p1>.*pattern1.*)(?P<p2>.*pattern2.*)(?P<p3>.*pattern3.*)" file.txt
È uno degli strumenti di grepping più veloci, poiché si basa su Rust “motore di regex che utilizza automi finiti, SIMD e ottimizzazioni letterali aggressive per rendere la ricerca molto veloce.
Vedi anche la richiesta di funzionalità correlate su GH-875 .
Risposta
Per trovare tutte le parole (o gli schemi), puoi eseguire grep
in un ciclo for
. Il vantaggio principale qui è la ricerca da un elenco di espressioni regolari .
Un esempio reale:
# File "search_all_regex_and_error_if_missing.sh" find_list="\ ^a+$ \ ^b+$ \ ^h+$ \ ^d+$ \ " for item in $find_list; do if grep -E "$item" file_to_search_within.txt then echo "$item found in file." else echo "Error: $item not found in file. Exiting!" exit 1 fi done
Ora eseguiamolo su questo file:
hhhhhhhhhh aaaaaaa bbbbbbbbb ababbabaabbaaa ccccccc dsfsdf bbbb cccdd aa caa
$ ./search_all_regex_and_error_if_missing.sh aaaaaaa aa ^a+$ found in file. bbbbbbbbb bbbb ^b+$ found in file. hhhhhhhhhh ^h+$ found in file. Error: ^d+$ not found in file. Exiting!
Commenti
- La tua logica è difettosa – Ho chiesto
ALL
, il tuo codice funziona come operatoreOR
, nonAND
. E btw. Per quello (OR
) è una soluzione molto più semplice data direttamente nella domanda. - @greenoldman La logica è semplice: il for ripeterà TUTTE le parole / schemi nellelenco, e se si trova nel file, lo stamperà. Quindi rimuovi semplicemente il else se ‘ non hai bisogno di unazione nel caso in cui la parola non sia stata trovata.
- Capisco la tua logica e la mia domanda: stavo chiedendo delloperatore
AND
, il che significa che il file è un risultato positivo solo se corrisponde al pattern A e al pattern B e pattern C e …AND
Nel tuo caso il file è positivo se ma tches pattern A o pattern B o … Vedi la differenza ora? - @greenoldman non è sicuro del motivo per cui pensi che questo ciclo non controlli la condizione AND per tutti i pattern? Quindi ‘ ho modificato la mia risposta con un esempio reale: cercherà nel file tutte le espressioni regolari della lista, e sulla prima che manca – uscirà con errore.
- Ce lhai davanti ai tuoi occhi, hai una corrispondenza positiva subito dopo lesecuzione della prima corrispondenza. Dovresti avere ” raccogliere ” tutti i risultati e calcolare
AND
su di essi. Quindi dovresti riscrivere lo script per eseguirlo su più file, quindi forse ti rendi conto che la domanda ha già una risposta e il tuo tentativo non porta nulla al tavolo, scusa.
foo
e le righe che contengonobar
” vedi utilizzo di grep per più pattern di ricerca