Wygląda na to, że elegancka prostota Basha gubi się na ogromnej stronie podręcznika.
Oprócz powyższych doskonałych rozwiązań, pomyślałem, że postaram się przedstawić wam ściągę na temat tego, jak bash analizuje i interpretuje wypowiedzi . Następnie, korzystając z tego przewodnika, przeanalizuję przykłady przedstawione przez pytającego, aby lepiej zrozumieć, dlaczego nie działają one zgodnie z przeznaczeniem.
Uwaga: Wiersze skryptu powłoki są używane bezpośrednio. Wpisane wiersze wprowadzania są najpierw rozszerzane w historii.
Każda linia uderzenia jest najpierw tokenizowana , czyli innymi słowy pocięta na tak zwane tokeny . (Tokenizacja występuje przed wszystkimi innymi rozszerzeniami, w tym nawiasami klamrowymi, tyldą, parametrem, poleceniem, arytmetyką, procesem, dzieleniem słów i rozwijaniem nazw plików).
Token tutaj oznacza część linii wejściowej oddzieloną (oddzieloną) jednym z tych specjalnych metaznaków:
space, - White space...
tab,
newline,
‘<’, - Redirection & piping...
‘|’,
‘>’
‘&’, - And/Both < | > | >> .or. &<file descriptor>
‘;’, - Command termination
‘(’, - Subshell, closed by - ‘)’
Bash używa wielu innych znaków specjalnych, ale tylko te 10 produkuje początkowe żetony.
Ponieważ jednak te metaznaki również muszą być czasami używane w ramach tokena, musi istnieć sposób na usunięcie ich specjalnego znaczenia. To się nazywa ucieczka. Uciekając odbywa się albo poprzez cytowanie ciąg jednego lub więcej znaków (np 'xx..', "xx..") lub poprzedzając indywidualny charakter z back-slash (tj \x). (Jest to trochę bardziej skomplikowane niż to, ponieważ cytaty również muszą być cytowane, a ponieważ podwójne cudzysłowy nie cytują wszystkiego, ale na razie wystarczy to uproszczenie).
Nie myl cytowania bash z pomysłem cytowania ciągu tekstu, jak w innych językach. Pomiędzy cudzysłowami w bash nie są ciągi, lecz sekcje wiersza wejściowego, w których metaznaki są znakami ucieczki, aby nie ograniczały tokenów.
Zauważ, że istnieje ważna różnica między ', a ", ale to na inny dzień.
Pozostałe nieskalowane metaznaki stają się następnie separatorami tokenów.
Na przykład,
$ echo "x"'y'\g
xyg
$ echo "<"'|'\>
<|>
$ echo x\; echo y
x; echo y
W pierwszym przykładzie są dwa tokeny wyprodukowane przez separator spacji: echoi xyz.
Podobnie w drugim przykładzie.
W trzecim przykładzie średnik jest uciekł, więc istnieją 4 żetony produkowane przez separator przestrzeni, echo, x;, echo, i y. Pierwszy token jest następnie uruchamiany jako polecenie i przyjmuje kolejne trzy tokeny jako dane wejściowe. Uwaga: 2. miejsce echonie jest wykonywane.
Ważną rzeczą do zapamiętania jest to, że bash najpierw szuka uciekających znaków ( ', "i \), a następnie szuka nieskalowanych ograniczników meta-znaków, w tej kolejności.
Jeśli nie uciekł, te 10 znaków specjalnych służy jako tokenograniczniki. Niektóre z nich mają również dodatkowe znaczenie, ale przede wszystkim są ogranicznikami tokenów.
Czego oczekuje grep
W powyższym przykładzie grep potrzebuje tych tokenów grep, string, filename.
Pierwsza próba pytania brzmiała:
$ grep (potem | tam) xx
W tym przypadku (, )i |to bez zmiany znaczenia znaków meta i tak służyć do podziału wkładu w te tokeny: grep, (, then, |, there, ), i x.x. grep chce zobaczyć grep, then|therei x.x.
Drugą próbą pytania było:
grep "(następnie | tam)" xx
Ten tokenizes w grep, (then|there), x.x. Możesz to zobaczyć, jeśli zamienisz grep na echo:
echo "(następnie | tam)" xx
(następnie | tam) xx