我不是 bash 专家,但最近我一直在编写 bash 脚本,而且每次都引用我的参数真的很麻烦。有什么办法可以改变这种 shell 行为吗?我希望我的字符串即使不引用它们也不会被分割
PS - 将 IFS 设置为 null 不起作用,因为所有参数都会被破坏。我想要的是写作时:
func1() {
echo $1 $2 $3
}
func2() {
echo "number of arguments func2 got: $#"
}
func2 $(func1 firstarg "second arg is a multi word string" "third arg is also a multi word string")
Run Code Online (Sandbox Code Playgroud)
会打印:
number of arguments func2 got: 3
Run Code Online (Sandbox Code Playgroud)
编辑,感谢评论指出:由于我的示例使用 echo,因此代码无论如何都会打印它得到 1 或 14 个参数,具体取决于您是否引用 func2 的参数。然而,我正在寻找一种从函数返回多个值的方法,而不会使它们被破坏,就像我提到的预期结果一样
谢谢!
要回答标题中的问题,禁用分词的方法是设置IFS
为空字符串。
但是您在文本中描述的内容更困难,在通过命令替换传递多个多单词字符串后保持它们不同。确实没有简单的方法可以做到这一点。
这里的根本问题是命令替换的结果(〜在其中调用的函数的标准输出的输出)只是一个字符串(字节流),并且您试图在其中容纳多个字符串。在一般情况下,这些字符串中包含任意内容,这是一个相当基本的问题。
这与将命令存储在变量中也没有太大区别,只是我们在这里进行了命令替换。
解决方法是保留一些字符用作分隔符,并将其设置IFS
为该字符。使用默认值IFS
,您将使用空格、制表符和换行符作为分隔符,这显然不适用于带有空格的字符串。如果IFS
设置为空字符串,则不会有这样的分隔符,因此您总是只会得到一个字段。
但是您可以设置IFS
为例如仅换行符(假设您的字符串不是多行):
#!/bin/bash
IFS=$'\n'
foo() {
printf "%s\n" "$@"
}
nargs() {
echo "number of arguments nargs got: $#"
}
nargs $(foo firstarg "multi word string" "also a multi word string")
Run Code Online (Sandbox Code Playgroud)
(但是,您不能在列表末尾使用空字符串,因为命令替换会删除所有尾随换行符,而不管IFS
.)
另一种方法是不使用函数的标准输出,而是将变量的名称传递给函数,并让函数通过 nameref 写入命名数组:
#!/bin/bash
bar() {
declare -n _out="$1"
shift
_out=("$@")
}
nargs() {
echo "number of arguments nargs got: $#"
}
bar tmparr firstarg "multi word string" "also a multi word string"
nargs "${tmparr[@]}"
Run Code Online (Sandbox Code Playgroud)
(如果调用的变量_out
也存在于函数外部,则变量作用域存在一些问题。)
另请注意,如果您有未加引号的扩展(变量或命令替换),它们的结果也将受到文件名通配的影响,因此类似的输出12 * 34
将受到严重破坏,除非您也禁用set -f
.