使用命令扩展作为for循环或初始化数组的参数

时间:2018-08-23 13:10:10

标签: shell

我在for循环和数组初始化中使用函数的输出(字符串包含空格)时遇到问题。 我想知道为什么下面的表达式具有不同的行为。

当普通字符串以for in结构传递时,它执行得很好。

$ for str in 'a b' 'c d'; do echo $str; done
a b
c d

但是当我使用函数的输出时,情况就不同了。

foo ()
{
    echo "'a b' 'c d'"
}
$ for str in $(foo); do echo $str; done
'a
b'
'c
d'

类似的情况也发生在初始化数组上:

$ strs=('a b' 'c d')
$ echo "${strs[@]}"
a b c d
$ echo "${strs[0]}"
a b

但是

$ strs=( $(foo) )
$ echo "${strs[@]}"
'a b' 'c d'
$ echo "${strs[0]}"
'a

使用函数的输出,该函数具有相同的常量值,但产生不同的结果。为什么会这样?其背后的内部机制是什么?

最重要的是,如何使用函数的输出获得与使用常量相同的结果。

看看这个问题的注释中的链接,它不仅包含这个问题,还包含很多帮助。

2 个答案:

答案 0 :(得分:1)

一种解决方法(假设您的所有数组元素都不能包含换行符)是仅输出未加引号的文本行,并使用readarray来填充数组。

foo () {
    echo 'a b'
    echo 'c d'
}

readarray -t strs < <(foo)
for str in "${strs[@]}"; do
    echo "$str"
done

答案 1 :(得分:1)

这可以通过while循环完成,而无需将命令输出存储在数组中

foo() {
    echo 'a b'
    echo 'c d'
}

foo | while read; do
    echo "$REPLY"
done

在bash 4.4.23和adb shell上进行了测试