Например, следующая команда не работает:
if [[-e xyz]]; then echo File exists;fi
Кш дает следующую ошибку
[[-e: command not found
Это потому, что «[[-» неоднозначно?
command-line
syntax
ksh
AcBap
источник
источник
[[
является ключевым словом - предположительно дерево синтаксического анализа оболочки требует, чтобы ключевые слова были очерченыОтветы:
Самое простое объяснение было бы, потому что в руководстве это выглядит
[[ expression ]]
так, что должно быть пространство между[[
иexpression
и закрытием]]
. Но, конечно, мы можем попытаться взглянуть на это более подробно. Оболочки имеют несколько сложную грамматику и в значительной степени полагаются на понятие «разбиение слов». В частности, руководство ksh (1) заявляет:Таким образом, как указано в руководстве, последовательность символов
[[-e
считается словом оболочки.ksh
будет искать такую команду в списке встроенных и специальных операторов (например,for
илиwhile
), затем искать внешнюю команду - и вуаля - ни одна не найдена, поэтому появляется сообщение об ошибке о команде не найдена.В этом случае
[[
также не специальные метасимволы. Если бы это было так, то-e
часть[[-e
была бы названа словом оболочки, а не аргументом для[[
самого себя. Однако[[
описывается как составная команда, а в руководстве говорится следующее:Таким образом,
[[
чтобы быть распознанным как составная команда, это должно быть первое слово команды или списка команд, которое согласно предыдущему определению «слова» подразумевает, что оно должно быть отделено пробелами, символами табуляции или переводами строки от других слова / аргументы.В комментариях вы спросили : «Почему анализатор не может остановиться, как только найдет» [[»шаблон, и рассматривает его как начало условной команды?» Краткий ответ, вероятно, объясняется тем, что: 1) влияние
[
синтаксиса, поскольку оно изначально было внешней командой, и для POSIX соответствие стандарту существует как внешняя команда даже сегодня, и 2) потому что анализатор оболочки построен так. Оболочка синтаксического анализатора может распознавать другие специальные символы, не разделенные пробелами,echo $((2+2))
и(echo foobar)
отлично работать. Возможно, в будущем, когдаksh
разработка возобновится, или, как представляется, будет форк или клон (например,mksh
илиpdksh
), кто-то будет реализовывать синтаксис без пробелов в[[-e
.Смотрите также:
[[
называется «зарезервированным словом» (см. Раздел 2.9 языка командных команд оболочки ). По определению POSIX зарезервированное слово должно быть разделено пробелами. В отличие(
от этого, оператор является стандартным, и в разделе 2.9 говорится, что «представления включают интервалы между токенами в некоторых местах, где<blank>
s не требуется (когда один из токенов является оператором)». См. Соответствующее обсуждение: грамматика оболочки POSIX: почему группе скобок нужен первый пробел, а вспомогательной - нет?источник
char
это ключевое слово, но вы все равно не можете писатьcharsomeletter = 'A';
и ожидать, что парсер остановится после просмотраchar
.i--<=++j
, и у компилятора нет проблем с синтаксическим анализомi -- <= ++ j
._
). Кш имеет(
как оператор , так и(echo hello)
разбирает как( echo hello )
. Этоif
,{
,[[
и другие ключевые слова , иifx
,{x
и[[x
каждый один маркер - например , какcharsomeletter
это один C маркер. Напротив, без кавычек(x
в ksh есть два токена - например, какi--
два токена в C. То, что концептуально даже означает быть оператором, различается между оболочками в стиле Борна (например, ksh) и C. Но Питер А. Шнайдер указал на реальное лексическое сходство.Важно отметить, что
[
это команда, и в[[
ее основе лежит ключевое слово shell в bash и ksh[
.[[
используется аналогично[
. Иногда вы можете даже заменить[
]
с[[
]]
без каких - либо изменений в поведении. При использовании[
, как и любой команды, между командой и ее аргументами обязательно должен быть пробел. То же самое относится и к[[
.Раньше было только
/usr/bin/[
. Сейчас большинство оболочек[
встроено для повышения эффективности, но синтаксис тот же. В оболочках, которые предоставляют[[
, он функционирует как более универсальная альтернатива[
.Вот описание для
[
Bash:Так
[
что эквивалентноtest
(кроме ожидания]
аргумента в самом конце).help test
даст еще больше подробностей об этом. Вы можете сравнить это сhelp [[
.Также есть справочная страница для внешней команды
[
(man \[
).На случай, если
[
ни[[
там нет команды. Полное слово[[-e
есть.if [[-e
делает тест на истину / ложь. Так есть ли команда[[-e
?Да. Или нет
[[-e
это то, что есть: ничего, что оболочка не понимает, поэтому она предполагает, что это ее собственная команда. ;-)источник
[[-e
- это потенциально допустимое (если странно выглядящее) имя команды.Пространство является разделителем и является обязательным. Как вы можете видеть из
shellcheck
:(Поддерживаются как ksh, так и bash,
[[
и они не работают без пробела. Shellcheck выдает именно такой вывод с помощью похожих сценариев ksh и bash, содержащих эту строку с ошибками.)Для чего нужны разделители, имеет отношение к токенам и лексиконам .
источник
ksh
оболочке в вопросе. Bash заимствует[[
операторуksh
и в этом вопросе их поведение идентично, но я был бы осторожен предположений , поскольку есть некоторые существенные различия междуksh
иbash
поведения и внутренних органов . Это потому, что shellcheck работает на скрипте bash, он не обязательно может быть подходящим инструментом для скриптов ksh. Просто что-то иметь в виду при приближении к разным снарядам[[
встроенные правила. Я ни в коем случае не делал вывод, чтоksh
это оболочка, в которойshellcheck
могут быть обнаружены ошибки. Я надеюсь, что другие ценятksh
иbash
являются двумя разными интерпретаторами. Спасибо за упоминание этого. Также стоит отметить[[
встроенный bash, а[
внешнюю команду.[
это также встроенная в bash :) manpages.ubuntu.com/manpages/bionic/man7/bash-builtins.7.html Но вы не за горами -[
или вамtest
требуется внешняя команда. В те времена, когда оригинальная оболочка Bourne[
была фактически внешней командой, она все еще существует в настоящее время,/usr/bin/[
поскольку POSIX требует, чтобы она была внешней командой pubs.opengroup.org/onlinepubs/009695399/utilities/test.html POSIX требуется очень мало для быть встроенным pubs.opengroup.org/onlinepubs/009695399/idx/sbi.html Встроенный[
- для эффективностиksh
; используйте hashbang или-s ksh
. Кстати, ksh и bash имеют[[
«встроенный», но, в отличие от этого, это ключевое слово[
- встроенная оболочка . (ksh :;whence -v [ [[
bashtype [ [[
:) Встроенные и внешние команды синтаксически похожи. Один[[
из отличий от этого[
заключается в том, что он[[
подавляет некоторые расширения в своих аргументах, которые он не может использовать как встроенные - так же, как{
и при группировке, если бы он не был встроенным. Это может быть то, почему{x
(или[[x
) быть одним жетоном кажется странным. Я думаю, что правильно сказать, что встроенные функции и ключевые слова лексически, но не синтаксически похожи. @SergiyKolodyazhnyy[[
может быть внешней командой! То есть это может быть программа, а не какой-то синтаксис, поддерживаемый вашей оболочкой напрямую. Поддержка синтаксиса без пробелов возможна,ksh
но в системах с внешним[[
интерфейсом она не будет работать, поэтому по соображениям совместимости лучше сохранить необходимое пространство.[[
Например, BusyBox предоставляет в качестве внешней команды .источник
Так как
[[-e
может участвовать в расширении оболочки (его можно использовать какдля того, чтобы перечислить все файлы, начинающиеся с буквы между
[
иe
включительно), было бы полным беспорядком, если бы[
и]
были специальными символами, не участвующими в нормальном разделении слов с пробелами.источник