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?
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?
Odpowiedzi:
Najprostszym wyjaśnieniem byłoby, ponieważ w instrukcji wydaje się, [[ expression ]]więc nie musi być przestrzeń pomiędzy [[a expressioni 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:
Powłoka zaczyna analizować dane wejściowe, dzieląc je na słowa. Słowa, które są sekwencjami znaków, są rozdzielane niecytowanymi białymi znakami (spacja, tabulator i nowa linia) lub metaznakami (<,>, |,;, &, (i)). Oprócz ograniczania słów spacje i tabulatory są ignorowane, podczas gdy znaki nowej linii zwykle ograniczają polecenia.
Tak jak podano w instrukcji, sekwencja znaków [[-ejest uważana za słowo powłoki. kshszukałby takiego polecenia na liście wbudowanych i operatorów specjalnych (takich jak forlub while), 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 -eczęść [[-ebył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:
Polecenia złożone są tworzone przy użyciu następujących słów zastrzeżonych - słowa te są rozpoznawane tylko wtedy, gdy nie są cytowane i jeśli są używane jako pierwsze słowo polecenia (tzn. Nie mogą być poprzedzone przypisaniem parametrów ani przekierowaniem):
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, gdy kshprogramowanie zostanie wznowione lub pojawi się widelec lub klon (jak mkshlub pdksh), ktoś zaimplementuje składnię bez spacji [[-e.
[[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?charjest słowem kluczowym, ale nadal nie można pisać charsomeletter = 'A';i oczekiwać, że parser zatrzyma się po zobaczeniu char.
i--<=++j, a kompilator nie ma problemu z analizowaniem tego jako i -- <= ++ j.
_). Ksh ma (jako operator i (echo hello)analizuje jako ( echo hello ). To if, {, [[, i inne słowa kluczowe , a ifx, {xi [[xkażdy jeden żeton - podobnie jak charsomeletterto jeden żeton C. W przeciwieństwie do tego, cudzysłow (xw ksh to dwa tokeny - podobnie jak i--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:
$ help [
[: [ arg... ]
Evaluate conditional expression.
This is a synonym for the "test" builtin, but the last argument must
be a literal `]', to match the opening `['.
[Jest to więc równoważne z test(poza oczekiwaniem ]argumentu na samym końcu). help testpoda jeszcze więcej szczegółów. Możesz to porównać do help [[.
Istnieje również strona podręcznika dla zewnętrznego polecenia [( man \[).
W przypadku
if [[-e
[nie [[ma polecenia. Pełne słowo [[-eto.if [[-esprawia, że jest to test na wartość prawda / fałsz. Czy istnieje polecenie [[-e? Czy to dlatego, że „[[-” jest niejednoznaczny?
Tak. Albo nie. [[-ejest tym, czym jest: nic, co powłoka rozumie, więc zakłada, że jest to jej własne polecenie. ;-)
[[-eto potencjalnie poprawna (choć dziwnie wyglądająca) nazwa polecenia.
Przestrzeń jest ogranicznikiem i jest wymagana. Jak widać z shellcheck:
$ shellcheck gmail-browse-msgs-algorithm.sh
In gmail-browse-msgs-algorithm.sh line 847:
[[$Today != "${DaysArr[ i + DAY_DELETED_ON_NDX ]}" ]] && continue
^-- SC1035: You need a space after the [[ and before the ]].
(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 .
kshshell w pytaniu. Bash pożycza [[operatora przed kshiw tej kwestii ich zachowanie jest identyczne, ale byłbym ostrożny z założeniami, jak istnieje kilka istotnych różnic kshi bashzachowań 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, że kshjest to powłoka, w której shellcheckmożna znaleźć błędy. Mam nadzieję, że inni to docenią kshi bashsą 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 - [lub testwymagane 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ści
ksh; 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 [ [[bash type [ [[:) 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, kshale 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 .
Ponieważ [[-emoże uczestniczyć w rozszerzaniu powłoki (może być używany jak
echo [[-e]*
aby wymienić wszystkie pliki zaczynające się od litery pomiędzy [i ewłą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.
[[jest słowem kluczowym - przypuszczalnie parsowanie drzewa powłoki wymaga, aby słowa kluczowe zostały określone przez spacje