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: echo
e 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 ° echo
non 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 token
delimitatori. 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|there
e 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