Na przykład następujące polecenie nie działa:
if [[-e xyz]]; then echo File exists;fi
ksh daje następujący błąd
[[-e: command not found
Czy to dlatego, że „[[-” jest niejednoznaczny?
command-line
syntax
ksh
AcBap
źródło
źródło
[[
jest słowem kluczowym - przypuszczalnie parsowanie drzewa powłoki wymaga, aby słowa kluczowe zostały określone przez spacjeOdpowiedzi:
Najprostszym wyjaśnieniem byłoby, ponieważ w instrukcji wydaje się,
[[ expression ]]
więc nie musi być przestrzeń pomiędzy[[
aexpression
i zamykanie]]
. Ale oczywiście możemy spróbować przyjrzeć się temu bardziej szczegółowo. Muszle mają nieco złożoną gramatykę i polegają w dużej mierze na koncepcji „dzielenia słów”. W szczególności instrukcja ksh (1) stwierdza:Tak jak podano w instrukcji, sekwencja znaków
[[-e
jest uważana za słowo powłoki.ksh
szukałby takiego polecenia na liście wbudowanych i operatorów specjalnych (takich jakfor
lubwhile
), a następnie szukał polecenia zewnętrznego - i voilà - nie znaleziono, stąd pojawia się komunikat o błędzie dotyczący polecenia nie znalezionego.W tym przypadku
[[
nie są też specjalnymi metaznakami. Gdyby tak było, ta-e
część[[-e
byłaby uważana za słowo powłoki, a nie argument[[
sam w sobie. Jest jednak[[
opisany jako polecenie złożone, a instrukcja mówi:Aby więc
[[
mógł zostać rozpoznany jako polecenie złożone, musi być pierwszym słowem polecenia lub listy poleceń, co zgodnie z poprzednią definicją „słowa” oznacza, że muszą być one oddzielone spacjami, tabulatorami lub znakami nowej linii od innych słowa / argumenty.W komentarzach zapytałeś : „Dlaczego parser nie może zatrzymać się, gdy tylko znajdzie wzorzec” [[”, i traktuje to jako początek polecenia warunkowego?” Krótka odpowiedź jest prawdopodobnie spowodowana 1) wpływem
[
składni, ponieważ pierwotnie była to komenda zewnętrzna, a dla POSIX standardowa zgodność istnieje już jako komenda zewnętrzna, a 2) ponieważ parser powłoki jest tak zbudowany. Analizator składni powłoki rozpoznaje inne znaki specjalne rozdzielane spacjami:echo $((2+2))
i(echo foobar)
działa doskonale. Być może w przyszłości, gdyksh
programowanie zostanie wznowione lub pojawi się widelec lub klon (jakmksh
lubpdksh
), ktoś zaimplementuje składnię bez spacji[[-e
.Zobacz też:
[[
nazywane jest „słowem zastrzeżonym” (patrz sekcja 2.9 języka poleceń powłoki ). Według definicji POSIX słowo zastrzeżone musi być oddzielone spacjami. Natomiast(
operator jest, a standardowe stany w sekcji 2.9 „reprezentacje obejmują odstępy między tokenami w niektórych miejscach, w których<blank>
s nie byłoby konieczne (gdy jeden z tokenów jest operatorem)”. Zobacz pokrewną dyskusję: Gramatyka powłoki POSIX: Dlaczego grupa Brace potrzebuje pierwszej przestrzeni, a podpowłoki nie?źródło
char
jest słowem kluczowym, ale nadal nie można pisaćcharsomeletter = 'A';
i oczekiwać, że parser zatrzyma się po zobaczeniuchar
.i--<=++j
, a kompilator nie ma problemu z analizowaniem tego jakoi -- <= ++ j
._
). Ksh ma(
jako operator i(echo hello)
analizuje jako( echo hello )
. Toif
,{
,[[
, i inne słowa kluczowe , aifx
,{x
i[[x
każdy jeden żeton - podobnie jakcharsomeletter
to jeden żeton C. W przeciwieństwie do tego, cudzysłow(x
w ksh to dwa tokeny - podobnie jaki--
dwa tokeny w C. To, co koncepcyjnie oznacza nawet, że jest operatorem, różni się między powłokami typu Bourne'a (jak ksh) i C. Ale Peter A. Schneider zwrócił uwagę na prawdziwe podobieństwo leksykalne .Należy zauważyć, że
[
jest to polecenie, a słowo kluczowe powłoki[[
w bash i ksh jest oparte[
.[[
jest używany w podobny sposób jak[
. Czasami można nawet zastąpić[
]
z[[
]]
bez zmiany zachowań. W przypadku[
, jak każdego polecenia, spacja jest obowiązkowa między poleceniem a jego argumentami. To samo dotyczy[[
.Kiedyś mieliśmy tylko
/usr/bin/[
. Teraz większość powłok ma[
wbudowaną wydajność - ale składnia jest taka sama. W powłokach, które to zapewniają[[
, działa ona jako bardziej wszechstronna alternatywa dla[
.Oto opis
[
w bash:[
Jest to więc równoważne ztest
(poza oczekiwaniem]
argumentu na samym końcu).help test
poda jeszcze więcej szczegółów. Możesz to porównać dohelp [[
.Istnieje również strona podręcznika dla zewnętrznego polecenia
[
(man \[
).W przypadku
[
nie[[
ma polecenia. Pełne słowo[[-e
to.if [[-e
sprawia, że jest to test na wartość prawda / fałsz. Czy istnieje polecenie[[-e
?Tak. Albo nie.
[[-e
jest tym, czym jest: nic, co powłoka rozumie, więc zakłada, że jest to jej własne polecenie. ;-)źródło
[[-e
to potencjalnie poprawna (choć dziwnie wyglądająca) nazwa polecenia.Przestrzeń jest ogranicznikiem i jest wymagana. Jak widać z
shellcheck
:(Zarówno obsługa ksh, jak i bash
[[
i nie działa bez spacji. Shellcheck daje dokładnie takie wyjście z podobnymi skryptami ksh i bash zawierającymi tę błędną linię.)Dlaczego separatory są potrzebne, mają związek z tokenami i leksykonami .
źródło
ksh
shell w pytaniu. Bash pożycza[[
operatora przedksh
iw tej kwestii ich zachowanie jest identyczne, ale byłbym ostrożny z założeniami, jak istnieje kilka istotnych różnicksh
ibash
zachowań i wewnętrznych. To dlatego, że shellcheck działa na skrypcie bash, niekoniecznie może być odpowiednim narzędziem dla skryptów ksh. Tylko coś, o czym należy pamiętać zbliżając się do różnych pocisków[[
wbudowane reguły. W żaden sposób nie wywnioskowałem, żeksh
jest to powłoka, w którejshellcheck
można znaleźć błędy. Mam nadzieję, że inni to doceniąksh
ibash
są dwoma różnymi tłumaczami. Dziękuję, że o tym wspomniałeś. Warto również zauważyć[[
wbudowane bash, podczas gdy[
jest to polecenie zewnętrzne.[
jest też wbudowany w bash :) manpages.ubuntu.com/manpages/bionic/man7/bash-builtins.7.html Ale nie jesteś daleko -[
lubtest
wymagane jest, aby być zewnętrznym poleceniem. W czasach, gdy oryginalna powłoka Bourne'a[
była w rzeczywistości zewnętrzną komendą i nadal istnieje,/usr/bin/[
ponieważ POSIX wymaga, aby była to zewnętrzna komenda pubs.opengroup.org/onlinepubs/009695399/utilities/test.html Bardzo niewiele jest wymaganych przez POSIX do bądź wbudowany pubs.opengroup.org/onlinepubs/009695399/idx/sbi.html Wbudowany[
jest dla wydajnościksh
; użyj hashbanga lub-s ksh
. Btw, ksh i bash mają[[
„wbudowane”, ale jest to słowo kluczowe , w przeciwieństwie[
do wbudowanej powłoki . (ksh :;whence -v [ [[
bashtype [ [[
:) Wbudowane i zewnętrzne polecenia są podobne pod względem składniowym. Jednym ze sposobów[[
różni się od[
tego, że[[
tłumi pewne rozszerzenia w swoich argumentach, których nie mógł jako wbudowane - podobnie jak{
grupowanie, gdyby nie było wbudowane. Być może dlatego{x
(lub[[x
) bycie jednym żetonem wydaje się dziwne. Myślę, że słusznie jest powiedzieć, że wbudowane i słowa kluczowe są leksykalnie, ale nie podobne pod względem składniowym . @SergiyKolodyazhnyy[[
może być poleceniem zewnętrznym! Oznacza to, że może to być program, a nie jakaś składnia obsługiwana bezpośrednio przez powłokę. Obsługa składni bez przestrzeni byłaby możliwa,ksh
ale zawiodłaby w systemach z zewnętrznymi,[[
więc ze względu na kompatybilność lepiej zachować wymaganą przestrzeń.BusyBox udostępnia
[[
na przykład jako polecenie zewnętrzne .źródło
Ponieważ
[[-e
może uczestniczyć w rozszerzaniu powłoki (może być używany jakaby wymienić wszystkie pliki zaczynające się od litery pomiędzy
[
ie
włącznie), byłby to kompletny bałagan, jeśli[
i]
były znaki specjalne, które nie uczestniczą w normalnej spacji rządzone słowo podziału.źródło