Как я могу назначить вывод функции переменной с помощью bash?

97

У меня есть функция bash, которая производит некоторый вывод:

function scan {
  echo "output"
}

Как я могу присвоить этот вывод переменной?

т.е. VAR = сканирование (конечно, это не работает - это делает VAR равным строке "сканирование")

Brent
источник
1
Связанный: stackoverflow.com/q/3236871/435605
AlikElzin-kilaka

Ответы:

145
VAR=$(scan)

Точно так же, как и для программ.

Роберт Обрик
источник
3
Я обнаружил, что новые строки удаляются, когда я сделал "echo $ VAR". Если вместо этого я процитировал $ VAR, он сохранил символы новой строки.
Brent
2
Это не на 100% верно. Подстановка команд всегда удаляет завершающие символы новой строки.
TheBonsai
7
Это создает подоболочку; есть ли способ сделать это в той же оболочке?
Limited Atonement
24

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

VAR=$(scan)

В большинстве случаев это простой способ добиться желаемого результата. Ниже я опишу частные случаи.

Сохранение завершающих символов новой строки:

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

function scan2 () {
    local nl=$'\x0a';  # that's just \n
    echo "output${nl}${nl}" # 2 in the string + 1 by echo
}

# append a character to the total output.
# and strip it with %% parameter expansion.
VAR=$(scan2; echo "x"); VAR="${VAR%%x}"

echo "${VAR}---"

печатает (сохранено 3 символа новой строки):

output


---

Используйте выходной параметр: избегайте подоболочки (и сохраняя новые строки)

Если функция пытается «вернуть» строку в переменную, то в bash v4.3 и выше можно использовать то, что называется a nameref. Namerefs позволяет функции принимать имя одного или нескольких выходных параметров переменных. Вы можете назначать вещи переменной nameref, и это как если бы вы изменили переменную, на которую она «указывает / ссылается».

function scan3() {
    local -n outvar=$1    # -n makes it a nameref.
    local nl=$'\x0a'
    outvar="output${nl}${nl}"  # two total. quotes preserve newlines
}

VAR="some prior value which will get overwritten"

# you pass the name of the variable. VAR will be modified.
scan3 VAR

# newlines are also preserved.
echo "${VAR}==="

печатает:

output

===

У этой формы есть несколько преимуществ. А именно, он позволяет вашей функции изменять среду вызывающего без использования глобальных переменных повсюду.

Примечание: использование namerefs может значительно повысить производительность вашей программы, если ваши функции сильно зависят от встроенных функций bash, поскольку это позволяет избежать создания подоболочки, которая сразу после этого удаляется. Обычно это имеет смысл для небольших функций, которые часто используются повторно, например, функций, заканчивающихся наecho "$returnstring"

Это актуально. https://stackoverflow.com/a/38997681/5556676

init_js
источник
0

Я думаю, что init_js должен использовать declare вместо local!

function scan3() {
    declare -n outvar=$1    # -n makes it a nameref.
    local nl=$'\x0a'
    outvar="output${nl}${nl}"  # two total. quotes preserve newlines
}
Хамид Реза Хасани
источник
localвстроенный будет принимать какие - либо варианты , что declareвстроенная команда будет принимать. из быстрого теста также кажется, что declare -nв области видимости функции также предоставляется локальная область видимости переменной. кажется они здесь взаимозаменяемы.
init_js 06