Як я можу призначити вихід функції для змінної за допомогою bash?


98

У мене є функція bash, яка видає певний результат:

function scan {
  echo "output"
}

Як я можу призначити цей результат змінній?

тобто VAR = сканування (звичайно, це не працює - це робить VAR рівним рядку "сканування")


Відповіді:


146
VAR=$(scan)

Точно так само, як і для програм.


3
Я виявив, що нові рядки зачищаються, коли я зробив "echo $ VAR". Якщо замість цього я цитував $ VAR, він зберігав нові рядки.
Брент

2
Це не на 100% правильно. Заміна команди завжди знімає нові рядки.
TheBonsai,

7
Це створює під оболонку; чи є спосіб зробити це в одній оболонці?
Обмежена спокута

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 і вище, можна використовувати те, що називається 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


0

Я думаю, що init_js повинен використовувати декларацію замість локальної!

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.