Насколько я знаю, [[
это расширенная версия [
, но я смущен, когда вижу [[
в качестве ключевого слова и [
отображается как встроенный.
[root@server ~]# type [
[ is a shell builtin
[root@server ~]# type [[
[[ is a shell keyword
TLDP говорит
Встроенный может быть синонимом системной команды с тем же именем, но Bash реализует ее внутренне. Например, команда Bash echo отличается от команды / bin / echo, хотя их поведение практически идентично.
а также
Ключевое слово - это зарезервированное слово, токен или оператор. Ключевые слова имеют особое значение для оболочки и действительно являются строительными блоками синтаксиса оболочки. В качестве примеров, пока, делай, и! являются ключевыми словами. Подобно встроенному, ключевое слово жестко запрограммировано в Bash, но в отличие от встроенного, ключевое слово само по себе не является командой, а представляет собой субъединицу командной конструкции. [2]
Разве это не должно быть как [
и [[
ключевое слово? Есть ли что-то, что мне здесь не хватает? Кроме того, эта ссылка подтверждает, что оба [
и [[
должны принадлежать к одному и тому же виду.
источник
if "[" $x -eq 3 ]
работает , как ожидалось (поскольку Bash выглядит для команды под названием[
, и это есть), ноif "[[" $x -eq 3 ]]
ничего не работает (потому что еще раз Bash ищет команду соответствующего имени, но нет[[
команда)./usr/bin/echo
, но это не значит, что это не встроенная функция .Ответы:
Разница между
[
и[[
является довольно фундаментальной.[
это команда. Его аргументы обрабатываются так же, как и любые другие аргументы команд. Например, рассмотрим:Оболочка развернется
$name
и выполнит как разбиение по словам, так и генерацию имени файла для результата, как и для любой другой команды.Например, следующее не удастся:
Для правильной работы цитаты необходимы:
[[
является ключевым словом оболочки и его аргументы обрабатываются в соответствии со специальными правилами. Например, рассмотрим:Оболочка будет расширяться,
$name
но, в отличие от любой другой команды, она не будет выполнять ни разбиение слов, ни генерацию имени файла для результата. Например, следующее будет выполнено успешно, несмотря на наличие пробелов вname
:Резюме
[
является командой и подчиняется тем же правилам, что и все другие команды, которые выполняет оболочка.Поскольку
[[
это ключевое слово, а не команда, оболочка обрабатывает его специально и работает по совершенно другим правилам.источник
man bash
. См., В частности, разделы, озаглавленные «ПРОСТОЕ РАСПРОСТРАНЕНИЕ КОМАНД» и «КОМАНДНОЕ ИСПОЛНЕНИЕ». В дополнение к[[
, другие Баш ключевые слова включаютif
,then
,while
и «дело». Для ключевых слов нет общих правил: каждое ключевое слово является особым случаем.man bash
включает в себя детали для каждого.В V7 Unix - где дебютировала оболочка Bourne -
[
называлсяtest
и существовал только как/bin/test
. Итак, код, который вы написали бы сегодня как:вы бы написали вместо этого как
Эта вторая нотация все еще существует, и я обнаружил, что она более ясна в отношении того, что происходит: вы вызываете вызываемую команду
test
, которая оценивает ее аргументы и возвращает код состояния выхода, которыйif
используется для решения, что делать дальше. Эта команда может быть встроена в оболочку или может быть внешней программой.[
как альтернатива,test
пришедшая позже. ² Это может быть встроенный синоним дляtest
, но он также предоставляется как/bin/[
в современных системах для оболочек, которые не имеют его в качестве встроенного.[
иtest
может быть реализовано с использованием того же кода. Это относится/bin/[
и/bin/test
к OS X, где это жесткие ссылки на один и тот же исполняемый файл. В результате реализация полностью игнорирует завершающий элемент]
: она не требуется, если вы вызываете ее как/bin/[
, и не жалуется если вы делаете предоставить его/bin/test
.⁴Ничто из этой истории не влияет
[[
, потому что никогда не было изначальной программы под названием[[
. Он существует исключительно внутри тех оболочек, которые реализуют его как расширение оболочки POSIX .Часть различия между «встроенным» и «ключевым словом» обусловлена этой историей. Это также отражает тот факт, что синтаксические правила для синтаксического анализа
[[
выражений отличаются, как указано в ответе Джона 1024.⁵Примечания:
Когда вы смотрите на это таким образом, становится ясно, почему вы должны помещать пробелы
[
в сценарии оболочки, в отличие от того, как скобки и скобки работают в большинстве других языков программирования. Если синтаксический анализатор команд оболочки разрешилif["$x"...
, он также должен был бы разрешитьiftest"$x"...
Это произошло около 1980 года.
/bin/[
В моей копии Ancient Unix V7 от 1979 года не существует, и неman test
документирует ее как псевдоним. В соответствующей записи мужчина страницы я имею в пре-релиз копию системы III руководства с 1980 года, он будет в списке.ls -i /bin/[ /bin/test
Но не рассчитывайте на это поведение. Встроенная версия Bash
[
требует закрытия]
, и ее встроеннаяtest
реализация будет жаловаться, если вы ее предоставите.Различие между встроенными и внешними командами также может иметь значение по другой причине: две реализации могут вести себя по-разному. Это относится ко
echo
многим системам. Поскольку существует только одна реализация, нет необходимости проводить такое различие для ключевого слова.источник
builtin
иkeyword
различие между[
и ,[[
когда оба обеспечивает те же функциональные возможности ( за исключением того , что[[
приходит с большим количеством функций , чем[
)?[[
будучи ключевым словом, позволяет bash делать то, что невозможно,[
например, цитирование не нужно много времени, потому что оболочка знает, что это переменная. То есть на обработку командной строки влияет использование ключевого слова, а не использование встроенного - это происходит намного позже.[
встроенную функцию , но код закомментирован.cd
является встроенным, но он ничего не скрывает (cd
не может быть реализован как внешняя программа).[[
ключевого слова позволяет оболочке использовать специальные правила синтаксического анализа для своих аргументов. Таким образом, увы, мой upvote идет к John1024.[
изначально была просто внешней командой, другое название для/bin/test
. Но некоторые команды, такие как[
иecho
, используются так часто в сценариях оболочки, что разработчики оболочки решили скопировать код непосредственно в саму оболочку, а не запускать другой процесс каждый раз, когда они используются. Это превратило эти команды в «встроенные», хотя вы все равно можете вызывать внешнюю программу через ее полный путь.[[
пришел намного позже Хотя встроенная функция реализована внутри оболочки, она анализируется как внешние команды. Как объясняется в ответе Джона 1024, это означает, что для переменных без кавычек будет выполнено разбиение по словам, а токены как>
и<
обрабатываются как перенаправление ввода / вывода. Это делало написание сложных выражений сравнения неудобным.[[
был создан как синтаксис оболочки, так что он мог быть проанализирован идеосинкразически. Внутри[[
переменных отсутствует разделение слов,<
и они>
могут использоваться как операторы сравнения,=
могут вести себя по-разному в зависимости от того, указан ли следующий параметр в кавычках или нет, и т. Д. Это все удобства, которые[[
проще использовать, чем традиционная[
команда / встроенная команда.Они не могли просто перекодировать в
[
такой синтаксис, потому что это было бы несовместимым изменением для миллионов скриптов. Используя новый[[
синтаксис, который ранее не существовал, они могли бы полностью изменить способ, которым он используется, с совместимостью вверх.Это похоже на эволюцию, которая привела к
$((...))
синтаксису для арифметических выражений, который в основном заменил традиционнуюexpr
команду.источник
Поздние
[[
вbash
это оптимизация в[
.У классики
[
есть один большой недостаток, когда он часто используется для выполнения тривиальной операции: он будет порождать новый процесс каждый раз:(Он создает новое адресное пространство только для сравнения
0
и1
! Каждый раз!)Я думаю, что основным моментом добавления
[[
было сделать так, чтобы выражение выражения внутри[
не порождало лишний процесс. Но то, как[
работает, не может быть изменено - это создаст много путаницы и проблем. Итак, оптимизация была реализована с новым именем, более эффективным способом, а именно командой встроенной оболочки.Это стало ключевым словом в синтаксисе оболочки как побочный эффект.
В то время, когда время
[
использовалось первым, это был правильный способ сделать это с помощью внешнего процесса.источник
[
изначально это была внешняя команда, она была добавлена в качестве встроенной в оболочку довольно рано, вероятно, к моменту выпуска Unix System III и определенно до выпуска Unix System V. Таким образом, «дополнительный процесс» не был проблемой целую вечность. Однако синтаксис остался неизменным - он обрабатывался так, как если бы он был внешней командой.[
и другое - это означает некоторые изменения ...