Сохранять возвращаемое значение и запускать не из подоболочек - PullRequest
0 голосов
/ 19 мая 2018

Я вызываю некоторую функцию, которая устанавливает VARIABLE на какое-то значение и возвращает другое значение.Мне нужно сохранить значение VARIABLE и присвоить возвращаемое значение функции другому VAR.Вот что я попробовал:

bar() {
        VAR="$(foo)"
        echo $VARIABLE >&2
        echo $VAR >&2
}

foo() {
        VARIABLE="test"
        echo "retval"
}
bar

Но он печатает

retval

Есть ли способ сделать это?

Ответы [ 3 ]

0 голосов
/ 19 мая 2018

BASH не возвращает значение вызывающей стороне, как это делают традиционные функциональные языки программирования.Единственное, что функции BASH могут возвращать (по существу), это «коды выхода» в результате выполнения функции.

Чтобы позволить функции предоставлять результат другой функции, вы должны использовать глобальные переменные.По умолчанию все переменные являются глобальными по объему, если не указано иное.

Вот набор функций с некоторыми эхо-операторами, которые могут помочь вам понять это:

#!/bin/bash

export VARIABLE=""

bar() {
        echo ">>> In function bar() ... "
        echo "        _var :: $_var"
        echo "    VARIABLE :: $VARIABLE"

        echo ">>> Setting '_var' to value 'local to bar' ... "
        local _var="local to bar"

        echo ">>> calling function foo() ... "
        foo
        echo ">>> Back in function bar() ... "

        echo "        _var :: $_var"
        echo "    VARIABLE :: $VARIABLE"
}

foo() {
        echo ">>> In function foo() ... "

        local _var="local to foo"
        VARIABLE="I'm a global variable"

        echo "        _var :: $_var"
        echo "    VARIABLE :: $VARIABLE"
}
bar

В приведенном выше примере мы устанавливаем переменную "_var" как локальную вобъем.Когда «bar ()» срабатывает, мы устанавливаем значение локального «_var» как «local to bar».Впоследствии мы вызываем функцию "foo ()";который устанавливает локальную переменную "_var" в значение "local to foo".

Мы также устанавливаем глобальную переменную "VARIABLE" в значение "I'm global variable".

Когда выполнение возвращается к функции "bar ()", мы печатаем наши переменные и _var.VARIABLE приводит к строке «Я глобальная переменная».

Подробнее о возвращаемых значениях из функций в BASH см. Вопрос Возвращаемое значение в функции Bash .

Вот результаты вышеупомянутого:

>>> In function bar() ...
        _var ::
    VARIABLE ::
>>> Setting '_var' to value 'local to bar' ...
>>> calling function foo() ...
>>> In function foo() ...
        _var :: local to foo
    VARIABLE :: I'm a global variable
>>> Back in function bar() ...
        _var :: local to bar
    VARIABLE :: I'm a global variable

Обратите внимание, что мы никогда не устанавливаем значение VARIABLE в функции "bar ()".Он устанавливается в "foo ()", и впоследствии мы получаем доступ к результатам с помощью глобальной переменной.

Локальные переменные "_var" также показывают, что значения являются только "локальными" для каждой функции, и, указав, что они являются локальными, они не имеют значения или значения вне самой функции.

Вы можете использовать субобстрел, чтобы делать то, что вы хотите.Однако подоболочки работают в отдельном пространстве процесса, поэтому вы часто будете получать непреднамеренные побочные эффекты.Для использования в примере подоболочки:

#!/bin/bash

export VARIABLE="default global value"

function bar()
{
    VAR=$(foo)
    echo "VARIABLE :: $VARIABLE"
    echo "     VAR :: $VAR"
}

function foo()
{
    # in theory, VARIABLE is globally scoped, but called in a
    # subshell, it won't impact/change the calling environment
    export VARIABLE='test'
    echo "$VARIABLE"
}

bar

Хотя захват вывода с помощью подоболочки работает таким образом - если ваша функция возвращает или выводит более одного значения, вы можете столкнуться с странным поведением, которого вы не делалинамерены.Приведенный выше пример иллюстрирует, что случайное наблюдение за функциями указывает, что «foo ()» изменит значение «VARIABLE» в глобальной области видимости.Но так как он запускается в подоболочке ('$ (foo)') - он вообще не меняет глобального значения VARIABLE.

Это может привести к незначительным логическим ошибкам в больших скриптах, и я бы посоветовал не использовать этот метод.Вот вывод приведенного выше фрагмента:

VARIABLE :: default global vaule
     VAR :: test
0 голосов
/ 19 мая 2018

Ну, это может быть некрасиво, но -

В bash все переменные являются глобальными, если не объявлено local.Следовательно, вы можете назначить VAR непосредственно в foo:

bar() {
        #### VAR="$(foo)"
        foo                  # Just call it
        echo $VARIABLE >&2
        echo $VAR >&2
}

foo() {
        VARIABLE="test"
        #### echo "retval"
        VAR="retval"         # What would have gone in $VAR before
}
bar

Вывод:

test
retval
0 голосов
/ 19 мая 2018

ksh имеет удобную конструкцию подстановки команд без подшаблонов для этого:

#!/bin/ksh
foo() {
  echo "cat"
  variable="dog"
}
output="${ foo }"
echo "Output is $output and the variable is $variable"

В bash и других оболочках вместо этого вы должны использовать временный файл:

#!/bin/bash

foo() {
  echo "cat"
  variable="dog"
}

# Create a temp file and register it for autodeletion
file="$(mktemp)"
trap 'rm "$file"' EXIT

# Redirect to it and read it back
foo > "$file"
output="$(< "$file")

echo "Output is $output and the variable is $variable"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...