Функции выполняются как подпроцессы в Bash?

28

В Advanced Bash-Scripting Guide , в примере 27-4 , 7-я строка снизу, я прочитал это:

Функция выполняется как подпроцесс.

Я сделал тест в Bash, и кажется, что приведенное выше утверждение неверно.

Поиски на этом сайте, Bash Man, и моя поисковая система не проливают свет.

У вас есть ответ и вы хотели бы объяснить?

Tomasz
источник
12
Как уже отмечалось, это руководство вводит в заблуждение до крайности. Вместо этого я рекомендую Wooledge Bash Guide .
Подстановочный

Ответы:

36

Расширенное руководство по написанию сценариев не всегда надежно, и его примеры сценариев содержат устаревшие методы, такие как использование устаревших обратных галочек для подстановки команд, т. Е. `command`Вместо $(command).

В данном конкретном случае это явно неправильно.

Раздел о функциях оболочки в (каноническом) руководстве по Bash однозначно утверждает, что

Функции оболочки выполняются в текущем контексте оболочки; не создан новый процесс для их интерпретации.

Энтони Дж - справедливость для Моники
источник
10
«Расширенное руководство по написанию сценариев, как правило, ненадежно». Очень верно.
John1024
1
Можете ли вы дать ссылки в поддержку вашего первого предложения?
Уилл Воусден
5
@WillVousden, как будет выглядеть ссылка здесь? Куча примеров технических недостатков руководства? Документ, в котором эксперты в сообществе bash ранее отмечали, что это ненадежно? Поможет ли это, если член stackoverflow с золотым значком в bash только что согласился в комментарии? : p
Кодзиро
3
@WillVousden Я не думаю, что то, что вы хотите, существует в самой надежной форме. В прошлом Мендель Купер обновлял и исправлял проблемы с руководством, но нет общедоступной системы отслеживания ошибок или списка ошибок. (Возможно, это самое ужасное заявление, которое я могу сделать.) Поэтому, когда мы находим изъян (видимый или реальный), все, что мы можем сделать, - это написать автору по электронной почте и надеяться на лучшее.
Кодзиро
3
@WillVousden, ... если вам нужна история о том, как долго в канале freenode #bash было достигнуто согласие о том, что следует избегать ABS, см. Wooledge.org/~greybot/meta/abs - второе поле в каждой строке это временная метка, а первым является имя пользователя; Я собираюсь надеяться, что утверждения о том, что имена пользователей, о которых идет речь, очень уважаемые люди, достаточно.
Чарльз Даффи
32

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

  • когда вы запускаете их в фоновом режиме с &
  • когда вы запускаете их как ссылку в конвейере

Перенаправления или дополнительные env. переменные не будут вызывать новый подоболочек:

hw(){
    echo hello world from $BASHPID
    echo var=$var
} 
var=42 hw >&2
echo $BASHPID  #unexports var=42 and restores stdout here

Если вы определяете функцию с круглыми скобками вместо фигурных скобок:

hw()(
  echo hello world from $BASHPID
)
hw 
echo $BASHPID

это всегда будет работать в новом процессе.

Подстановка команд $()также всегда создает процессы в bash (но не в ksh, если вы запускаете встроенные команды внутри него).

PSkocik
источник
Я не знал f() (...), разрешено. Есть ли другие определения, кроме {...}и (...)? В Bash я еще не знаком с другими.
Томаш
1
@tomas Вы можете использовать function hw { echo hello world; } синтаксис (нет необходимости, ()если вы печатаете , functionи вы можете указать перенаправления сразу после финала }или )как в hw(){ echo error; } >&2. Вот и все.
PSkocik
2
Это ответ, о котором я сразу подумал, и он абсолютно правильный. Это следует голосовать как правильный ответ. f()(...)всегда выполняйте собственную оболочку, а f(){...}не выполняйте.
rexkogitans
11
Примечание: bash-функции принимают любую составную команду, поэтому foo() [[ x = x ]]допустимо и определение функции. Однако, если вы посмотрите на функцию с, type fooвы увидите, что это все еще синтаксический сахар для foo() { [[ x = x ]]; }. То же самое относится и к функциям subshell: bar() ( : )становится bar() { ( : ); }.
Кодзиро
1
@kojiro приятно +1. не знал этого
PSkocik
9

Рассматриваемая команда из этого примера выглядит следующим образом:

echo ${arrayZ[@]/%e/$(replacement)}

Пример позже заявляет:

#    $( ... ) is command substitution.
#    A function runs as a sub-process.

Будучи благотворительными для ABS Guide, они, очевидно, хотели написать, что функция выполняется внутри подстановки команд, а команда внутри подстановки команд выполняется в подоболочке .

John1024
источник
Это очень вводит в заблуждение. Спасибо за вашу интерпретацию.
Томаш
5
@tomas "очень вводит в заблуждение". Да очень. В отличие от Руководства по АБС, Wiki Грега - отличный источник расширенной информации о bash.
John1024
1
Приветствия. Что вы думаете об этом: wiki.bash-hackers.org/start ?
Томаш
@ Томас Я не знаю из первых рук об этом.
John1024
2
@tomas, ... мое личное мнение о bash-hackers wiki - это отличный источник. Я не прошел через это всесторонне, как у меня вики Wooledge, но это имеет тенденцию быть точным и точно написанным.
Чарльз Даффи