Bash 扩展之谜
Bash Expansion Mystery
这是一个关于 Whosebug 的非常 "popular" 的主题,不幸的是,我在查看其他问题时未能弄清楚这一点。无论如何,让我们考虑以下情况。
一个函数获取一堆字符串参数,如下所示:
some_function "give some" "string arguments"
这个函数做的第一件事是将这些参数放入一个数组中,例如 array[0] 给出 "give some" 而 array[1] 给出 "string arguments"
现在假设我有一个字符串数组 some_array
并想对其调用 some_function。我如何 "transform" 该数组使其工作?
以下是一些不起作用的示例:
function print_args() {
local arr=( "$@" )
i=0;
for item in "${arr[@]}"
do
echo "[$i] -> '$item'"
(( i++ ))
done
}
echo "example"
print_args "this is" "the desired" "behavior"
echo -e "----------------\n"
some_array=( "\"does NOT\"" "\"seem to\"" "\"work\"" )
stringified_array=$(printf "%s " "${some_array[@]}")
echo "stringified array: [$stringified_array]"
echo "1) passing $some_array"
print_args $some_array
echo -e "---------------------------\n"
echo "2) passing \"$some_array\""
print_args "$some_array"
echo -e "---------------------------\n"
echo "3) passing $stringified_array"
print_args $stringified_array
echo -e "---------------------------\n"
echo "4) passing \"$stringified_array\""
print_args "$stringified_array"
echo -e "---------------------------\n"
这是输出
example
[0] -> 'this is'
[1] -> 'the desired'
[2] -> 'behavior'
----------------
stringified array: ["does NOT" "seem to" "work" ]
1) passing $some_array
[0] -> '"does'
[1] -> 'NOT"'
---------------------------
2) passing "$some_array"
[0] -> '"does NOT"'
---------------------------
3) passing $stringified_array
[0] -> '"does'
[1] -> 'NOT"'
[2] -> '"seem'
[3] -> 'to"'
[4] -> '"work"'
---------------------------
4) passing "$stringified_array"
[0] -> '"does NOT" "seem to" "work" '
---------------------------
我想我理解 1) 和 2) 并且只是出于绝望而尝试了它们。我相信我也理解 4)。现在我的大问题是我不明白 3) 到底是怎么回事,更重要的是我如何 "stringify" 我的数组以实现我想要的。这里有一个重要的注意事项是,我想尝试 避免使用 eval
.
谢谢!
你可能认为你说的是 3):
print_args "does NOT" "seem to" "work"
但实际上 3) 等同于:
print_args '"does' 'NOT"' '"seem' 'to"' '"work"'
这是因为未加引号的参数变量 $stringified_array
在 IFS
之前被拆分成单词 它被传递给函数。字符串中的双引号只是字符串的一部分,not 不会引用空格。
尝试通过修改示例代码中的第 16-#17 行来查看会发生什么:
16c16
< stringified_array=$(printf "%s " "${some_array[@]}")
---
> stringified_array=$(printf "%s#" "${some_array[@]}")
17a18
> IFS=#
通过将 IFS
分配给未出现在您的字符串中的分隔符,您将
能够安全地 stringify 你的数组,尽管会有其他解决方案
不对数组进行字符串化。
希望这有帮助。
这是一个关于 Whosebug 的非常 "popular" 的主题,不幸的是,我在查看其他问题时未能弄清楚这一点。无论如何,让我们考虑以下情况。
一个函数获取一堆字符串参数,如下所示:
some_function "give some" "string arguments"
这个函数做的第一件事是将这些参数放入一个数组中,例如 array[0] 给出 "give some" 而 array[1] 给出 "string arguments"
现在假设我有一个字符串数组 some_array
并想对其调用 some_function。我如何 "transform" 该数组使其工作?
以下是一些不起作用的示例:
function print_args() {
local arr=( "$@" )
i=0;
for item in "${arr[@]}"
do
echo "[$i] -> '$item'"
(( i++ ))
done
}
echo "example"
print_args "this is" "the desired" "behavior"
echo -e "----------------\n"
some_array=( "\"does NOT\"" "\"seem to\"" "\"work\"" )
stringified_array=$(printf "%s " "${some_array[@]}")
echo "stringified array: [$stringified_array]"
echo "1) passing $some_array"
print_args $some_array
echo -e "---------------------------\n"
echo "2) passing \"$some_array\""
print_args "$some_array"
echo -e "---------------------------\n"
echo "3) passing $stringified_array"
print_args $stringified_array
echo -e "---------------------------\n"
echo "4) passing \"$stringified_array\""
print_args "$stringified_array"
echo -e "---------------------------\n"
这是输出
example
[0] -> 'this is'
[1] -> 'the desired'
[2] -> 'behavior'
----------------
stringified array: ["does NOT" "seem to" "work" ]
1) passing $some_array
[0] -> '"does'
[1] -> 'NOT"'
---------------------------
2) passing "$some_array"
[0] -> '"does NOT"'
---------------------------
3) passing $stringified_array
[0] -> '"does'
[1] -> 'NOT"'
[2] -> '"seem'
[3] -> 'to"'
[4] -> '"work"'
---------------------------
4) passing "$stringified_array"
[0] -> '"does NOT" "seem to" "work" '
---------------------------
我想我理解 1) 和 2) 并且只是出于绝望而尝试了它们。我相信我也理解 4)。现在我的大问题是我不明白 3) 到底是怎么回事,更重要的是我如何 "stringify" 我的数组以实现我想要的。这里有一个重要的注意事项是,我想尝试 避免使用 eval
.
谢谢!
你可能认为你说的是 3):
print_args "does NOT" "seem to" "work"
但实际上 3) 等同于:
print_args '"does' 'NOT"' '"seem' 'to"' '"work"'
这是因为未加引号的参数变量 $stringified_array
在 IFS
之前被拆分成单词 它被传递给函数。字符串中的双引号只是字符串的一部分,not 不会引用空格。
尝试通过修改示例代码中的第 16-#17 行来查看会发生什么:
16c16
< stringified_array=$(printf "%s " "${some_array[@]}")
---
> stringified_array=$(printf "%s#" "${some_array[@]}")
17a18
> IFS=#
通过将 IFS
分配给未出现在您的字符串中的分隔符,您将
能够安全地 stringify 你的数组,尽管会有其他解决方案
不对数组进行字符串化。
希望这有帮助。