首页 > 解决方案 > Bash 扩展之谜

问题描述

这是 stackoverflow 上一个非常“流行”的话题,不幸的是我在查看其他问题时无法弄清楚这一点。无论如何,让我们考虑以下场景。一个函数得到一堆字符串参数,如下所示: some_function "give some" "string arguments" 这个函数做的第一件事是将这些参数放入一个数组中,例如 array[0] 给出“给一些”,而 array[1] 给出“字符串参数”

现在假设我有一个字符串数组some_array并想在其上调用 some_function。我如何“转换”该数组以使其工作?

以下是一些不起作用的示例:

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) 到底发生了什么,更重要的是我如何“字符串化”我的数组以实现我想要的。这里的一个重要说明是,我想尽量避免使用 eval.

谢谢!

标签: bashshellvariable-expansion

解决方案


您可能希望您说的是 3):

print_args "does NOT" "seem to" "work"

但实际上 3) 相当于:

print_args '"does' 'NOT"' '"seem' 'to"' '"work"'

这是因为未引用的参数变量在传递给函数之前$stringified_array被拆分为单词。字符串中的双引号只是字符串的一部分,不能用来引用空格。IFS

尝试通过修改示例代码中的 #16-#17 行来查看会发生什么:

16c16
< stringified_array=$(printf "%s " "${some_array[@]}")
---
> stringified_array=$(printf "%s#" "${some_array[@]}")
17a18
> IFS=#

通过分配IFS一个未出现在字符串中的分隔符,您将能够安全地对数组进行字符串化,尽管还有其他解决方案不会对数组进行字符串化。
希望这可以帮助。


推荐阅读