2012-05-02 13 views
100

Sto passando un elenco di modelli di espressioni regolari a grep per verificare un file syslog. Di solito corrispondono a un indirizzo IP e una voce di registro;Grep regex NON contenente la stringa

grep "1\.2\.3\.4.*Has exploded" syslog.log 

E 'solo un elenco di modelli come la parte "1\.2\.3\.4.*Has exploded" sto passando, in un ciclo, quindi non può passare "-v", per esempio.

Sono confuso cercando di fare l'inverso di quanto sopra, un NON corrisponde a linee con un certo indirizzo IP ed errore così "! 1.2.3.4. * È esploso" corrisponderà alle linee di syslog per qualcosa di diverso da 1.2.3.4 che dice me è esploso. I deve essere in grado di includere un IP per NON corrispondere.

Ho visto vari post simili su StackOverflor, tuttavia usano schemi regex che non riesco a far funzionare con grep. Qualcuno può fornire un esempio operativo per grep per favore?

UPDATE: Questo sta accadendo in uno script come questo;

patterns[1]="1\.2\.3\.4.*Has exploded" 
patterns[2]="5\.6\.7\.8.*Has died" 
patterns[3]="\!9\.10\.11\.12.*Has exploded" 

for i in {1..3} 
do 
grep "${patterns[$i]}" logfile.log 
done 
+0

Vuoi dire che a volte * * desidera abbinare un modello, ma altre volte vuole abbinare tutto * tranne * un certo modello? (questo sembra un requisito strano, ma qualunque cosa). In tal caso, perché non si itera su due diversi elenchi di modelli? – beerbajay

+0

Beh, non sono molto esperto in regex; Non voglio grep per "Has Exploded" perché non voglio sapere questo su ogni dispositivo di registrazione, quindi posso in qualche modo grep per "Has Exploded" e! 9.10.11.12 in una dichiarazione? – jwbensley

+0

Se lo si deve assolutamente fare in una dichiarazione, le occhiate negative sono la strada da percorrere, come suggerisce Neil. Vedi il mio commento lì. – beerbajay

risposta

183

grep partite, grep -v fa l'inverso. Se avete bisogno di "match A ma non B" di solito si usa tubi:

grep "${PATT}" file | grep -v "${NOTPATT}" 
+0

Questo sta andando nel bel mezzo di un ciclo come ho detto e sto passando il PATTERN a grep quindi non posso usare "-v" come ho detto. Sto facendo il giro di un elenco di PATTERN e passando a grep. – jwbensley

+1

Si può effettivamente usare '-v' e si può usare in un ciclo. Forse devi essere più specifico sui tuoi limiti, o forse hai un'idea sbagliata su come dovrebbe funzionare lo script. Prova a postare del codice. – beerbajay

+0

Grazie a beerbajay, ho aggiunto un codice tagliato al post originale per dare un po 'di contesto. Capisci cosa intendo adesso? – jwbensley

9
(?<!1\.2\.3\.4).*Has exploded 

È necessario eseguire questo con -P avere lookbehind negativo (Perl espressioni regolari), in modo che il comando è:

grep -P '(?<!1\.2\.3\.4).*Has exploded' test.log 

Prova questo. Usa lookbehind negativo per ignorare la riga se è preceduta da 1.2.3.4. Spero possa aiutare!

+1

Sono quasi sicuro che 'grep' non supporta il lookaround. A meno che non stiate usando Gnu 'grep' e usate il parametro' --P' per far sì che usi un motore PCRE. –

+0

No, grep non supporta questo tipo di Regex; $ Grep -P (<\ 1 \ 0,2 \ 0,3 \ 0,4?!) Test.log -bash: errore di sintassi nei pressi di token imprevisto '(' – jwbensley

+0

Si sta andando ad avere bisogno di citare l'espressione regolare se contiene caratteri che sarebbe interpretato dalla shell – beerbajay

2
patterns[1]="1\.2\.3\.4.*Has exploded" 
patterns[2]="5\.6\.7\.8.*Has died" 
patterns[3]="\!9\.10\.11\.12.*Has exploded" 

for i in {1..3} 
do 
grep "${patterns[$i]}" logfile.log 
done 

dovrebbe essere la stessa di

egrep "(1\.2\.3\.4.*Has exploded|5\.6\.7\.8.*Has died)" logfile.log | egrep -v "9\.10\.11\.12.*Has exploded"  
Problemi correlati