Come posso grep per questo o quello (2 cose) in un file?


38

Ho un file che contiene "then" e "there".

io posso

$ grep "then " x.x
x and then some
x and then some
x and then some
x and then some

e posso

$ grep "there " x.x
If there is no blob none some will be created

Come posso cercare entrambi in un'unica operazione? Provai

$ grep (then|there) x.x

-bash: errore di sintassi vicino al token imprevisto `('

e

grep "(then|there)" x.x
durrantm.../code
# (Nothing)

Risposte:


54

È necessario inserire l'espressione tra virgolette. L'errore che stai ricevendo è il risultato dell'interpretazione di bash (come carattere speciale.

Inoltre, devi dire a grep di usare espressioni regolari estese.

$ grep -E '(then|there)' x.x

Senza le espressioni regolari estese, si deve sfuggire alla |, (e ). Si noti che qui vengono utilizzate le virgolette singole. Bash tratta in modo particolare le barre rovesciate tra virgolette doppie.

$ grep '\(then\|there\)' x.x

Il raggruppamento non è necessario in questo caso.

$ grep 'then\|there' x.x

Sarebbe necessario per qualcosa del genere:

$ grep 'the\(n\|re\)' x.x

3
Vedi anche grep $'then\nthere'e grep -e then -e there. Si noti che \|non è standard nei BRE. Il resto è. Tratta Bash backslash specialmente tra virgolette solo prima ", $, \ , `e ritorno a capo.
Stéphane Chazelas,

1
Qual è lo scopo di x.x?
alex

7

Solo un breve addendum, la maggior parte dei sapori ha un comando chiamato egrep che è solo grep con -E. Personalmente mi piace molto di più scrivere

egrep "i(Pod|Pad|Phone)" access.log

Che usare grep -E


2

Il materiale documentato in EXPRESSIONS REGOLARI nella (o almeno nella mia pagina man) è in realtà per regexps estesi ;

grep comprende tre diverse versioni della sintassi delle espressioni regolari: "base", "estesa" e "perl". In GNU grep, non vi è alcuna differenza nella funzionalità disponibile tra sintassi base ed estesa. In altre implementazioni, le espressioni regolari di base sono meno potenti. La seguente descrizione si applica alle espressioni regolari estese; le differenze per le espressioni regolari di base sono riassunte in seguito.

Ma grep non li usa per impostazione predefinita - è necessario l' -Einterruttore:

grep "(then|there)" x.x

Perché (di nuovo dalla pagina man):

Espressioni regolari di base vs estese

Nelle espressioni regolari di base i meta-caratteri?, +, {, |, (E) perdono il loro significato speciale; usa invece le versioni rovesciate \ ?, +, {, \ |, (e).

Quindi puoi anche usare:

grep "then\|there" x.x

Poiché le parentesi sono superflue in questo caso.


0

L'elegante semplicità di Bash sembra perdersi nella sua enorme pagina man.

Oltre alle eccellenti soluzioni di cui sopra, ho pensato di provare a darti un cheat sheet su come bash analizza e interpreta le dichiarazioni . Quindi usando questa tabella di marcia analizzerò gli esempi presentati dall'interrogante per aiutarti a capire meglio perché non funzionano come previsto.


Nota: le righe di script Shell vengono utilizzate direttamente. Le righe di input digitate vengono espanse per la prima volta nella cronologia.

Ogni riga bash viene prima tokenizzata , o in altre parole suddivisa in quelli che vengono chiamati token . (La tokenizzazione si verifica prima di tutte le altre espansioni, tra cui parentesi graffa, tilde, parametro, comando, aritmetica, processo, suddivisione delle parole ed espansione del nome file.)

Un token qui indica una parte della linea di input separata (delimitata) da uno di questi speciali meta-caratteri:

space,  - White space...
tab, 
newline,

‘<’,    - Redirection & piping...
‘|’, 
‘>’
‘&’,    - And/Both < | > | >>  .or.  &<file descriptor>

‘;’,    - Command termination

‘(’,    - Subshell, closed by -     ‘)’

Bash usa molti altri personaggi speciali ma solo questi 10 producono i token iniziali.

Tuttavia, poiché a volte anche questi meta-personaggi devono essere utilizzati all'interno di un token, deve esserci un modo per toglierne il significato speciale. Questo si chiama fuga. L'escaping viene fatto citando una stringa di uno o più caratteri, (cioè 'xx..', "xx.."), o anteponendo un singolo carattere con una barra rovesciata, (cioè \x). (È un po 'più complicato di così perché anche le virgolette devono essere citate e perché le doppie virgolette non citano tutto, ma questa semplificazione per il momento lo farà.)

Non confondere citando bash con l'idea di citare una stringa di testo, come in altre lingue. Ciò che si trova tra virgolette in bash non sono stringhe, ma piuttosto sezioni della riga di input con meta-caratteri con escape che non delimitano i token.

Nota, c'è una differenza importante tra ', e ", ma è per un altro giorno.

I restanti meta-caratteri senza escape diventano quindi separatori di token.

Per esempio,

$ echo "x"'y'\g
xyg

$ echo "<"'|'\>
<|>

$ echo x\; echo y
x; echo y

Nel primo esempio ci sono due token prodotti da un delimitatore di spazio: echoe xyz.

Allo stesso modo nel secondo esempio.

Nel terzo esempio la virgola è sfuggito, così ci sono 4 gettoni prodotti da un delimitatore spazio, echo, x;, echo, e y. Il primo token viene quindi eseguito come comando e accetta i successivi tre token come input. Si noti che il 2 ° echonon viene eseguito.


La cosa importante da ricordare è che bash primi sguardi di personaggi in fuga ( ', ", e \), e poi cerca delimitatori meta-caratteri escape, in questo ordine.

Se non sfuggiti, questi 10 caratteri speciali fungono da tokendelimitatori. Alcuni di essi hanno anche un significato aggiuntivo, ma prima di tutto sono delimitatori di token.


Cosa si aspetta grep

Nell'esempio sopra grep bisogno questi gettoni, grep, string, filename.

Il primo tentativo della domanda è stato:

$ grep (quindi | there) xx

In questo caso (, )e |sono meta caratteri escape e così servono a dividere l'ingresso in questi gettoni: grep, (, then, |, there, ), e x.x. grep vuole vedere grep, then|theree x.x.

Il secondo tentativo della domanda è stato:

grep "(then | there)" xx

Questo tokenizza in grep, (then|there), x.x. Puoi vederlo se cambi grep con echo:

echo "(then | there)" xx
(then | there) xx

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.