Вызов функции скрипта: функция против $(function)

Вызов функции скрипта: функция против $(function)

Для простоты рассмотрим следующий код:

#!/bin/bash

number=7

function doSomething() {
  number=8
}

doSomething
echo "$number"

Он печатает 8.

Но с:

#!/bin/bash

number=7

function doSomething() {
  number=8
}

$(doSomething)
echo "$number"

Он печатает 7.

У меня есть следующие вопросы:

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

решение1

Вы познаете тонкости замены команд.

Вызов

doSomething

— это простой вызов функции. Он выполняет функцию, как если бы вы скопировали и вставили команды функции в то место, где вы ее вызываете. Следовательно, он перезаписывает переменную numberновым значением 8.

Вызов

$(doSomething)

с другой стороны, этозамена команды. Он предназначен для выполнения функции ивернуть то, что функция напечатала stdout. Обычно он не используется «отдельно», а в переменных назначениях, например,

os_type=$(uname)

Это выполнит команду uname, которая в системе Linux выведет ее Linuxна консоль, и сохранит ее результат в переменной оболочки os_type. Поэтому не имеет смысла использовать подстановку команды с командой или функцией, которая ничего не выводит, как ваша doSomething. Действительно, поскольку подстановка $(doSomething)по сути является заполнителем для вывода doSomething, единственная причина, по которой вы не получите ошибку скрипта, заключается в том, что ваша функция ничего не выводит. Если бы вы указали, например,

$(uname)

вместо

$(doSomething)

ваша оболочка попыталась бы выполнить команду Linuxи сгенерировала бы

Linux: No such file or directory

ошибка (1) .

Ключевым моментом для понимания наблюдаемого вами эффекта является то, что при замене командкоманда выполняется в подоболочке, т. е. любые изменения переменных не распространяются обратно на оболочку, в которой вы выполняете основной скрипт. Поэтому, хотя внутренне он выполняет команды doSomethingи устанавливает переменную numberв 8, он делает это в своем собственном процессе оболочки, который не имеет ничего общего с процессом оболочки, который запускает ваш скрипт (за исключением того факта, что он stdoutизвлекается), и, следовательно, не может изменить переменную, которую numberвы использовали в основном скрипте.

Для дальнейшего чтения вы можете посмотреть

здесь на этом сайте, или

для более подробного обзора.


(1) С другой стороны, это означает, что вы можете использовать подстановку команд для выполнения команды, название которой вы не знаете на момент написания скрипта, но можете узнать, выполнив другую известную вам команду.

Связанный контент