【问题标题】:Escape comma in "$@" expansion"$@" 扩展中的转义逗号
【发布时间】:2016-08-14 06:59:22
【问题描述】:

"$@" 似乎让, 消失了。例如

param="123 1,2"
set echo $param
"$@"

这将回显“123 1 2”而不是“123 1,2”,但在某些情况下,, 需要作为命令的值。

而且这个好像和bash版本有关,用bash 4.1.2,结果是正确的,但是用4.2.46,逗号不见了。


编辑:

简而言之,可能是 nice 的责任:

我做了unset IFS 并且在终端中我给出的测试用例工作正常,但我的脚本却没有。

我实际上正在编写一个初始化脚本,我检查了/etc/init.d/functions 中的action() 函数,并添加了一些调试代码:

echo "$@" # added by me
unset IFS # added by me
"$@" && success $"$STRING" || failure $"$STRING"

回显的命令是正确的(nice -n -10 ovs-vswitchd ... --socket-mem 1024,1024),但在ps 结果中,nice 执行的实际命令变为ovs-vswitchd ... --socket-mem 1024 1024

我开始认为这可能是 nice 的错。

【问题讨论】:

  • 检查 IFS 的中断。
  • 这似乎是 bash 4.1 中的一个错误。我正在检查changelog for bash 4.2 看看是否有相关内容。
  • set -- "$param" 应该可以解决您的问题
  • 你的测试用例工作正常;你能提供一个minimal reproducible example 来演示nice 的行为吗?
  • echo "$@" 实际上并不能有效地代表真正正在运行的内容——您无法区分echo "foo bar"echo foo bar。相反,printf '%q ' "$@"; printf '\n'

标签: bash shell


【解决方案1】:

请在拆分参数之前直接在脚本中设置 IFS(在命令 set 之前)。例如做这样的事情:

oldIFS=$IFS
param="123 1,2"
IFS=" "  # put tabs and or newline if also wanted.
set echo $param
IFS=$oldIFS
"$@"

无论您以前的 IFS 是什么,这都可以工作。

【讨论】:

  • 如果 OP 想要进行字符串拆分,最好的做法是使用read -a,完全不依赖 IFS。 IFS= read -r -a args <<<"$param"; set -- echo "${args[@]}" 只在read 命令执行期间修改IFS,所以不需要恢复和返回旧值
  • ...这很重要,因为oldIFS 方法有问题:如果未设置旧值(unset IFS),那么上面的代码将导致之前的行为大不相同及之后。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-14
  • 2021-05-16
  • 2015-03-07
  • 2022-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多