如何使用bash将函数的输出分配给变量?


Answers:


144
VAR=$(scan)

与程序完全相同。


3
我发现当我执行“ echo $ VAR”时,换行符被剥离了。相反,如果我引用$ VAR,它将保留换行符。
布伦特

2
这不是100%正确的。命令替换总是删除尾随的换行符。
TheBonsai

7
这将创建一个子外壳;有什么办法可以在同一外壳中做到这一点?
有限赎罪

24

您可以在命令/管道中使用bash函数,否则将使用常规程序。这些功能也可用于子shell以及可传递的Command Substitution:

VAR=$(scan)

在大多数情况下是获得所需结果的直接方法。我将在下面概述特殊情况。

保留尾随的换行符:

Command Substitution的副作用(通常有用)之一是它将删除任何数量的尾随换行符。如果希望保留尾随的换行符,则可以在子shell的输出后附加一个哑字符,然后使用参数扩展剥离它。

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


---

使用输出参数:避免使用子shell(并保留换行符)

如果函数试图实现的是使用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

===

这种形式有一些优点。即,它允许您的函数修改调用方的环境,而无需在任何地方使用全局变量。

注意:如果您的函数严重依赖bash内置函数,则使用namerefs可以大大提高程序的性能,因为这样可以避免创建子shell,而该子shell不会在之后被丢弃。通常,对于经常重复使用的小功能,例如,以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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.