Каково использование круглых скобок `()` в определении функции оболочки?

Удалите известные хосты под ~ / .ssh / known_hosts, затем попытайтесь снова подключиться. Перед запуском конфигурации Ubuntu Core вы должны загрузить открытые ключи.

19
задан 11 April 2018 в 20:32

9 ответов

Без () синтаксис действительно был бы двусмысленным.

Должен быть какой-то однозначный синтаксис для определения функции и без существенного изменения другого синтаксиса оболочки, это не может быть: 1]

do_something {
    # one or more commands go here
}

Вы сказали, что это «не связано с его текущим синтаксисом», но это так! Обратите внимание, что при попытке запустить некоторые вы не получаете никакой синтаксической ошибки. Вы получаете ошибку, но это не ошибка синтаксиса. Вторая строка с } является синтаксической ошибкой, но первая строка не является. Вместо этого do_something { пытается запустить команду с именем do_something и передать { в качестве аргумента этой команде:

$ do_something {
do_something: command not found

Если уже существует команда с именем do_something, вы запускаете Это. Если уже есть функция, называемая do_something, вы вызываете ее. В общем, важно, чтобы синтаксис был однозначным, но также важно, чтобы можно было переопределить функцию, не называя ее случайно.

Как оболочка рассматривает { и (.

Поскольку type { скажет вам, { ключевое слово оболочки. Это делает его подобно [[. Если используется в ситуации, когда в противном случае это была бы команда, { несет специальную семантику. В частности, он выполняет группировку команд. В других ситуациях, однако, он может использоваться без привязки для обозначения символа {. Это включает в себя ситуацию передачи его как второго или последующего слова команды.

Конечно, Bash , который вы называете его , был разработан для обработки { иначе, чем его в настоящее время. Однако его синтаксис больше не был бы совместим с оболочкой POSIX, и Bash на самом деле не был бы оболочкой стиля Bourne и не мог бы запускать многие сценарии оболочки.

Напротив, является метасимволом оболочки. Он всегда обрабатывается специально, если он появляется в команде и не цитируется (с ' ', " " или \). Таким образом, в синтаксисе нет двусмысленности:

do_something() {
    # one or more commands go here
}

Это ничего не значит. Если у Bash нет функций, то это будет синтаксическая ошибка, по той же причине echo foo(bar) является синтаксической ошибкой.

Если вам действительно не нравится нотация (), вы можете использовать ключевое слово function и опустить это, как упоминает судовод. Обратите внимание, что это не является частью синтаксиса для определения функций в большинстве других оболочек в стиле Bourne, а в некоторых поддерживается, но функции определены таким образом, что имеют другую семантику - и поэтому скрипт, который его использует, не будет переносимым. (Причина, по которой этот синтаксис может быть однозначным, заключается в том, что function сам по себе является ключевым словом в Bash, что означает, что все, что следует за ним, является началом определения функции.)

Наконец, обратите внимание, что, хотя большинство функций определения используют { на практике, любая составная команда разрешена. Если у вас была функция, тело которой вы хотели всегда запускать в подоболочке, вы можете использовать ( ), а не { }.

41
ответ дан 22 May 2018 в 11:30
  • 1
    На более высоком уровне речь идет о человеческих ожиданиях и читаемости. В большинстве языков, особенно в C, fortran и других, которые были распространены вокруг того времени, когда были разработаны языки сценариев bash, функция / подпрограмма всегда имеет список аргументов, возможно пустой, заключенный в круглые скобки. Измените эту парадигму, и вам становится труднее понять язык. – jamesqf 11 April 2018 в 21:52

Без () синтаксис действительно был бы двусмысленным.

Должен быть какой-то однозначный синтаксис для определения функции и без существенного изменения другого синтаксиса оболочки, это не может быть:

do_something { # one or more commands go here }

Вы сказали, что это «не связано с его текущим синтаксисом», но это так! Обратите внимание, что при попытке запустить некоторые вы не получаете никакой синтаксической ошибки. Вы получаете ошибку, но это не ошибка синтаксиса. Вторая строка с } является синтаксической ошибкой, но первая строка не является. Вместо этого do_something { пытается запустить команду с именем do_something и передать { в качестве аргумента этой команде:

$ do_something { do_something: command not found

Если уже существует команда с именем do_something, вы запускаете Это. Если уже есть функция, называемая do_something, вы вызываете ее. В общем, важно, чтобы синтаксис был однозначным, но также важно, чтобы можно было переопределить функцию, не называя ее случайно.

Как оболочка рассматривает { и (.

Поскольку type { скажет вам, { ключевое слово оболочки. Это делает его подобно [[. Если используется в ситуации, когда в противном случае это была бы команда, { несет специальную семантику. В частности, он выполняет группировку команд. В других ситуациях, однако, он может использоваться без привязки для обозначения символа {. Это включает в себя ситуацию передачи его как второго или последующего слова команды.

Конечно, Bash , который вы называете его , был разработан для обработки { иначе, чем его в настоящее время. Однако его синтаксис больше не был бы совместим с оболочкой POSIX, и Bash на самом деле не был бы оболочкой стиля Bourne и не мог бы запускать многие сценарии оболочки.

Напротив, ( является метасимволом оболочки. Он всегда обрабатывается специально, если он появляется в команде и не цитируется (с ' ', " " или \). Таким образом, в синтаксисе нет двусмысленности:

do_something() { # one or more commands go here }

Это ничего не значит. Если у Bash нет функций, то это будет синтаксическая ошибка, по той же причине echo foo(bar) является синтаксической ошибкой.

Если вам действительно не нравится нотация (), вы можете использовать ключевое слово function и опустить это, как упоминает судовод. Обратите внимание, что это не является частью синтаксиса для определения функций в большинстве других оболочек в стиле Bourne, а в некоторых поддерживается, но функции определены таким образом, что имеют другую семантику - и поэтому скрипт, который его использует, не будет переносимым. (Причина, по которой этот синтаксис может быть однозначным, заключается в том, что function сам по себе является ключевым словом в Bash, что означает, что все, что следует за ним, является началом определения функции.)

Наконец, обратите внимание, что, хотя большинство функций определения используют { на практике, любая составная команда разрешена. Если у вас была функция, тело которой вы хотели всегда запускать в подоболочке, вы можете использовать ( ), а не { }.

41
ответ дан 17 July 2018 в 17:03

Без () синтаксис действительно был бы двусмысленным.

Должен быть какой-то однозначный синтаксис для определения функции и без существенного изменения другого синтаксиса оболочки, это не может быть:

do_something { # one or more commands go here }

Вы сказали, что это «не связано с его текущим синтаксисом», но это так! Обратите внимание, что при попытке запустить некоторые вы не получаете никакой синтаксической ошибки. Вы получаете ошибку, но это не ошибка синтаксиса. Вторая строка с } является синтаксической ошибкой, но первая строка не является. Вместо этого do_something { пытается запустить команду с именем do_something и передать { в качестве аргумента этой команде:

$ do_something { do_something: command not found

Если уже существует команда с именем do_something, вы запускаете Это. Если уже есть функция, называемая do_something, вы вызываете ее. В общем, важно, чтобы синтаксис был однозначным, но также важно, чтобы можно было переопределить функцию, не называя ее случайно.

Как оболочка рассматривает { и (.

Поскольку type { скажет вам, { ключевое слово оболочки. Это делает его подобно [[. Если используется в ситуации, когда в противном случае это была бы команда, { несет специальную семантику. В частности, он выполняет группировку команд. В других ситуациях, однако, он может использоваться без привязки для обозначения символа {. Это включает в себя ситуацию передачи его как второго или последующего слова команды.

Конечно, Bash , который вы называете его , был разработан для обработки { иначе, чем его в настоящее время. Однако его синтаксис больше не был бы совместим с оболочкой POSIX, и Bash на самом деле не был бы оболочкой стиля Bourne и не мог бы запускать многие сценарии оболочки.

Напротив, ( является метасимволом оболочки. Он всегда обрабатывается специально, если он появляется в команде и не цитируется (с ' ', " " или \). Таким образом, в синтаксисе нет двусмысленности:

do_something() { # one or more commands go here }

Это ничего не значит. Если у Bash нет функций, то это будет синтаксическая ошибка, по той же причине echo foo(bar) является синтаксической ошибкой.

Если вам действительно не нравится нотация (), вы можете использовать ключевое слово function и опустить это, как упоминает судовод. Обратите внимание, что это не является частью синтаксиса для определения функций в большинстве других оболочек в стиле Bourne, а в некоторых поддерживается, но функции определены таким образом, что имеют другую семантику - и поэтому скрипт, который его использует, не будет переносимым. (Причина, по которой этот синтаксис может быть однозначным, заключается в том, что function сам по себе является ключевым словом в Bash, что означает, что все, что следует за ним, является началом определения функции.)

Наконец, обратите внимание, что, хотя большинство функций определения используют { на практике, любая составная команда разрешена. Если у вас была функция, тело которой вы хотели всегда запускать в подоболочке, вы можете использовать ( ), а не { }.

41
ответ дан 23 July 2018 в 17:54

Маркер () указывает интерпретатору оболочки, что вы объявляете функцию.

$ do_something () { echo 'do it'; } ; do_something
do it

Альтернативой в bash является function

function do_something {
 echo 'do it'
}
[d2 ] или как однострочный, вы можете проверить

$ bash -c "function do_something { echo 'do it'; } ; do_something"
do it
15
ответ дан 22 May 2018 в 11:30
  • 1
    Ключевое слово function - это pre-POSIX ksh-ism, который поддерживает bash для обратной совместимости; однако bash поддерживает его плохо (не делая переменными function-local default, поскольку старый ksh сделал в объявленных в этой форме функциях). Следовательно, он не идеален для нового кода. См. wiki.bash-hackers.org/scripting/bsolete – Charles Duffy 11 April 2018 в 23:14
  • 2
    @CharlesDuffy, Спасибо за это объяснение :-) – sudodus 11 April 2018 в 23:26
  • 3
    @CharlesDuffy Вы говорите, что ksh и bash принимают некоторый синтаксис, который делает переменную local в ksh, но глобальную в bash? Это звучит не так. Мое понимание, основанное частично на , что post и проверка (в ksh93), заключается в том, что ksh делает переменными локальными в меньше ситуаций, чем bash, никогда больше , В bash функция typeset без -g в функции всегда объявляет локальную переменную. С ключевым словом function, bash и ksh scope одинаково , не так ли? – Eliah Kagan 12 April 2018 в 03:23

Как вы считаете, что это очень верно для вас!

Рассмотрите другие, совершенно тонкие стили скобок:

foo
{
  ...
}
foo
  {
    ...
  }
foo
  while ...; do ...; done # Look, ma! No braces!
foo
( ... ) # Look, ma! No braces and a subshell to boot!

Как оболочка скажет, что это определения функций, а не просто команда foo, за которой следуют списки команд? Во всех этих случаях необходим дополнительный фактор устранения неоднозначности, например ключевое слово () или function.

9
ответ дан 22 May 2018 в 11:30
  • 1
    Во-вторых, на самом деле это не OTBS, поскольку одно место, где OTBS позволяет скобки на новой строке, предназначено для определения функций. – muru 11 April 2018 в 11:59
  • 2
    Я думаю, что есть аргумент в пользу того, что вы были правы, чтобы охарактеризовать его как OTBS, потому что, в отличие от функций на C и C ++, определение функции в сценарии оболочки в стиле Bourne может быть вложенным непосредственно в тело другого определения функции и поэтому, возможно, не заслуживает того, чтобы его отличали. (Или, может быть, это стиль, популярный в программировании на Java, где методы получают свою открытую фигурную скобку в одной строке, а не OTBS.) В любом случае, вы прекрасно представляете, как синтаксис должен будет наложить жесткие ограничения на размещение фигурных скобок для работы вообще без () или что-то в этом роде. – Eliah Kagan 11 April 2018 в 12:08

Как вы считаете, что это очень верно для вас!

Рассмотрите другие, совершенно тонкие стили скобок:

foo { ... } foo { ... } foo while ...; do ...; done # Look, ma! No braces! foo ( ... ) # Look, ma! No braces and a subshell to boot!

Как оболочка скажет, что это определения функций, а не просто команда foo, за которой следуют списки команд? Во всех этих случаях необходим дополнительный фактор устранения неоднозначности, например ключевое слово () или function.

9
ответ дан 17 July 2018 в 17:03

Маркер () указывает интерпретатору оболочки, что вы объявляете функцию.

$ do_something () { echo 'do it'; } ; do_something do it

Альтернативой в bash является function

function do_something { echo 'do it' }

или как однострочный, вы можете проверить

$ bash -c "function do_something { echo 'do it'; } ; do_something" do it
15
ответ дан 17 July 2018 в 17:03

Как вы считаете, что это очень верно для вас!

Рассмотрите другие, совершенно тонкие стили скобок:

foo { ... } foo { ... } foo while ...; do ...; done # Look, ma! No braces! foo ( ... ) # Look, ma! No braces and a subshell to boot!

Как оболочка скажет, что это определения функций, а не просто команда foo, за которой следуют списки команд? Во всех этих случаях необходим дополнительный фактор устранения неоднозначности, например ключевое слово () или function.

9
ответ дан 23 July 2018 в 17:54
  • 1
    Во-вторых, на самом деле это не OTBS, поскольку одно место, где OTBS позволяет скобки на новой строке, предназначено для определения функций. – muru 11 April 2018 в 11:59
  • 2
    Я думаю, что есть аргумент в пользу того, что вы были правы, чтобы охарактеризовать его как OTBS, потому что, в отличие от функций на C и C ++, определение функции в сценарии оболочки в стиле Bourne может быть вложенным непосредственно в тело другого определения функции и поэтому, возможно, не заслуживает того, чтобы его отличали. (Или, может быть, это стиль, популярный в программировании на Java, где методы получают свою открытую фигурную скобку в одной строке, а не OTBS.) В любом случае, вы прекрасно представляете, как синтаксис должен будет наложить жесткие ограничения на размещение фигурных скобок для работы вообще без () или что-то в этом роде. – Eliah Kagan 11 April 2018 в 12:08

Маркер () указывает интерпретатору оболочки, что вы объявляете функцию.

$ do_something () { echo 'do it'; } ; do_something do it

Альтернативой в bash является function

function do_something { echo 'do it' }

или как однострочный, вы можете проверить

$ bash -c "function do_something { echo 'do it'; } ; do_something" do it
15
ответ дан 23 July 2018 в 17:54
  • 1
    Ключевое слово function - это pre-POSIX ksh-ism, который поддерживает bash для обратной совместимости; однако bash поддерживает его плохо (не делая переменными function-local default, поскольку старый ksh сделал в объявленных в этой форме функциях). Следовательно, он не идеален для нового кода. См. [D1] wiki.bash-hackers.org/scripting/bsolete – Charles Duffy 11 April 2018 в 23:14
  • 2
    @CharlesDuffy, Спасибо за это объяснение :-) – sudodus 11 April 2018 в 23:26
  • 3
    @CharlesDuffy Вы говорите, что ksh и bash принимают некоторый синтаксис, который делает переменную local в ksh, но глобальную в bash? Это звучит не так. Мое понимание, основанное частично на , что post и проверка (в ksh93), заключается в том, что ksh делает переменными локальными в меньше ситуаций, чем bash, никогда больше , В bash функция typeset без -g в функции всегда объявляет локальную переменную. С ключевым словом function, bash и ksh scope одинаково , не так ли? – Eliah Kagan 12 April 2018 в 03:23

Другие вопросы по тегам:

Похожие вопросы: