以各种方式被引用时,如何正确地转义bash变量 [英] How can I properly escape bash variables when being quoted in various ways
问题描述
我有以下代码:
set -o xtrace
openDirectory ()
{
lxterminal --command="zsh -c 'cd "$1"; zsh -i' "
}
# Handle argument.
if [ "$@" ]
then
openDirectory ~/Projects/Clients/"@1"
cd $1
fi
如果传递的参数中有空格,此操作将失败。
This fails if there is a space in the argument passed.
lxterminal '--command=zsh -c '\''cd /home/chris/Projects/Clients/Test' - 'Space; zsh -i'\'' '
cd Test - Space
cd: too many arguments
如何正确地避免这种情况?
How can I properly escape this? Is this even feasible to be done with something like bash?
推荐答案
假设封闭的外壳确实是bash(因为这个问题已被标记),这甚至可行吗? ),则可以使用 printf -v varname%q $ var
存储值 var $ c $的安全引用实例c>放入名为
varname
的变量中,例如:
Assuming the enclosing shell really is bash (as the question is tagged), you can use printf -v varname %q "$var"
to store a safely quoted instance of the value of var
into the variable named varname
, as such:
openDirectory()
{
local cd_cmd cmd
printf -v cd_cmd '%q ' cd "$1"
printf -v cmd '%q ' zsh -c "$cd_cmd && zsh -i"
lxterminal --command="$cmd"
}
printf'%q'
计算为给定字符串的版本,当bash eval
'ed时,该版本(或具有等效语义的任何外壳程序),求值为原始文字值。
printf '%q'
evaluates to a version of the given string which will, when eval
'ed by bash (or any shell with equivalent semantics), evaluate to the original literal value.
要解释为什么这样做是这样的:
To explain why this is done that way:
- 在上面,代码本身包含的所有引号字符都是句法而不是文字:取决于 all 引用和转义的
printf%q
。这是一种最佳实践方法:使用文字引号意味着生成的数据中的文字可以转义这些引号。 - 运行shell指令,例如
& &
通过外壳引号会将它们转换为文字数据。因此,当我们将&&
作为参数传递给<$ c $时,我们希望是文字数据,而不是语法c> -c ,但不是由远程Shell处理时的文字数据,这就是为什么它仅出现在 last 引用传递中的原因。
- In the above, all quote characters included in the code itself are syntactic rather than literal: We're depending on
printf %q
for all quoting and escaping. This is a best-practice approach: Using literal quotes means that literals inside the data being generated are able to escape those quotes. - Running shell directives such as
&&
through shell quoting will make them into literal data. Thus, we want the&&
to be literal data rather than syntax when we're passing it as an argument to-c
, but not literal data when handled by the remote shell -- this is why it's only present in the last quoting pass.
这篇关于以各种方式被引用时,如何正确地转义bash变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!