回显传递给带有可见引号的命令的确切命令行

Gem*_*lor 2 bash quoting

因此,我可以很高兴地在bash数组中建立一个命令行,然后用引号将其执行并获得每个引号的引号:

declare -a cmd_args
cmd_args=("-p" "dir path/with spaces")
mkdir "${cmd_args[@]}"
echo dir*/*
Run Code Online (Sandbox Code Playgroud)

但是,如何以一种有意义的方式将其回显到屏幕上,即向用户显示他们可以键入的命令,或者可以将其保存在日志文件中以备将来参考?所有这些看起来(基本上)是相同的:

echo runnimg mkdir with arguments ${cmd_args[@]}
echo runnimg mkdir with arguments "${cmd_args[@]}"
echo "runnimg mkdir with arguments '${cmd_args[@]}'"
echo "runnimg mkdir with arguments '${cmd_args[*]}'"

==> runnimg mkdir with arguments '-p dir path/with spaces'
Run Code Online (Sandbox Code Playgroud)

这显然是错误的命令。这并没有向用户显示他们可以键入的命令,或者我可以保留在日志文件中并在将来的日期重现的命令。我想看看:

runnimg mkdir with arguments '"-p" "dir path/with spaces"'
Run Code Online (Sandbox Code Playgroud)

我考虑过使用cat<<EOF

cat<<EOF 
"${cmd_args[@]}" 
EOF
Run Code Online (Sandbox Code Playgroud)

但实际上,这会在整个参数列表中产生一个很大的报价!这里有什么?这怎么可能永远是我的意图是什么?如果是这样,那我就有"${cmd_args[*]}"

这就是挑战。以用户可以说“是的,这是正确的命令”的方式打印命令。

对那些说“%p \ n”的人表示抱歉,但是对于日志文件来说这可能没问题,但是返回并对其进行“毫不含糊地”格式化以重新测试该命令仍然很麻烦,但它确实不够好交互式“这是命令反馈给用户”。

也许已经有一个答案,但是如果是这样,那么所有“总是引用您的论据”类型的答案就会淹没它。

Léa*_*ris 6

如果要打印带有引号的参数列表,而不管引号是否合适:

printf '"%s" ' "${cmd_args[@]}"
Run Code Online (Sandbox Code Playgroud)

如果要仅在需要时打印带引号或转义的参数列表:

printf '%q ' "${cmd_args[@]}"
Run Code Online (Sandbox Code Playgroud)

要做到这一点:

printf 'runnimg mkdir with arguments:'
printf ' %q' "${cmd_args[@]}"
Run Code Online (Sandbox Code Playgroud)

一个dash kshPOSIX兼容的外壳执行:

#!/usr/bin/env dash

#cmd_args=("-p" "dir path/with spaces")
# dash and POSIX shell don't have arrays
# but support setting the arguments like this:
set -- -p "dir path/with spaces"
printf 'runnimg mkdir with arguments:'
# dash built-in printf does not know about %q format,
# but system command printf does.
env printf ' %q' "$@"
echo

mkdir "$@"
Run Code Online (Sandbox Code Playgroud)

  • ''%q'`的方法很棒,因为它在视觉上是明确的,并且以一种可以复制粘贴到其他shell中的方式捕获有关参数的所有内容。如果参数包含例如“”或“ $”,则“'%s”'将不起作用 (2认同)