如何在以各种方式引用时正确转义 bash 变量
How can I properly escape bash variables when being quoted in various ways
我有以下代码:
set -o xtrace
openDirectory ()
{
lxterminal --command="zsh -c 'cd ""; zsh -i' "
}
# Handle argument.
if [ "$@" ]
then
openDirectory ~/Projects/Clients/"@1"
cd
fi
如果传递的参数中有 space,则此操作失败。
lxterminal '--command=zsh -c '\''cd /home/chris/Projects/Clients/Test' - 'Space; zsh -i'\'' '
cd Test - Space
cd: too many arguments
我怎样才能正确地逃避这个?这甚至可以用 bash?
之类的东西来完成吗?
尽管评论中提出了一个很好的建议,但作为处理此类问题的一般方法,您可以这样写:
set -o xtrace
openDirectory ()
{
local safe_path
printf -v safe_path "%q" ""
lxterminal --command="zsh -c 'cd $safe_path; zsh -i' "
}
为了更好地准备要作为参数传递给 lxterminal
的命令,请参阅 CharlesDuffy 的回答。
至于您的其余代码,我可能会使用以下代码:
# Handle argument.
if
[ -d "" ]
then
openDirectory ~/Projects/Clients/"@1"
cd ""
fi
如果参数 1 存在但为空(空字符串)但后面的参数不存在,则使用 "$@"
作为 if 条件可能产生 0(真)并执行正文。我想这不是你想要的。
我不确定“@1”是不是拼写错误,或者它是否真的是指您的 "Projects/Clients" 目录中名为“@1”的目录。但是 cd
的 ""
参数应该被引用,这是肯定的。
假设封闭的 shell 确实是 bash(因为问题被标记),您可以使用 printf -v varname %q "$var"
来存储 [=12= 的值的安全引用实例] 到名为 varname
的变量中,例如:
openDirectory()
{
local cd_cmd cmd
printf -v cd_cmd '%q ' cd ""
printf -v cmd '%q ' zsh -c "$cd_cmd && zsh -i"
lxterminal --command="$cmd"
}
printf '%q'
求值为给定字符串的一个版本,当 eval
被 bash(或具有等效语义的任何 shell)编辑时,求值为原始文字值。
解释为什么这样做:
- 在上面,代码本身中包含的所有引号字符都是句法而非文字:我们依赖
printf %q
进行 所有 引用和转义。这是最佳实践方法:使用文字引号意味着正在生成的数据中的文字能够转义这些引号。
- 运行 shell 指令,例如
&&
到 shell 引用将使它们成为文字数据。因此,当我们将其作为参数传递给 -c
时,我们 希望 &&
是文字数据而不是语法,但在处理时不是文字数据远程 shell -- 这就是为什么它只出现在 last 引用传递中的原因。
我有以下代码:
set -o xtrace
openDirectory ()
{
lxterminal --command="zsh -c 'cd ""; zsh -i' "
}
# Handle argument.
if [ "$@" ]
then
openDirectory ~/Projects/Clients/"@1"
cd
fi
如果传递的参数中有 space,则此操作失败。
lxterminal '--command=zsh -c '\''cd /home/chris/Projects/Clients/Test' - 'Space; zsh -i'\'' '
cd Test - Space
cd: too many arguments
我怎样才能正确地逃避这个?这甚至可以用 bash?
之类的东西来完成吗?尽管评论中提出了一个很好的建议,但作为处理此类问题的一般方法,您可以这样写:
set -o xtrace
openDirectory ()
{
local safe_path
printf -v safe_path "%q" ""
lxterminal --command="zsh -c 'cd $safe_path; zsh -i' "
}
为了更好地准备要作为参数传递给 lxterminal
的命令,请参阅 CharlesDuffy 的回答。
至于您的其余代码,我可能会使用以下代码:
# Handle argument.
if
[ -d "" ]
then
openDirectory ~/Projects/Clients/"@1"
cd ""
fi
如果参数 1 存在但为空(空字符串)但后面的参数不存在,则使用 "$@"
作为 if 条件可能产生 0(真)并执行正文。我想这不是你想要的。
我不确定“@1”是不是拼写错误,或者它是否真的是指您的 "Projects/Clients" 目录中名为“@1”的目录。但是 cd
的 ""
参数应该被引用,这是肯定的。
假设封闭的 shell 确实是 bash(因为问题被标记),您可以使用 printf -v varname %q "$var"
来存储 [=12= 的值的安全引用实例] 到名为 varname
的变量中,例如:
openDirectory()
{
local cd_cmd cmd
printf -v cd_cmd '%q ' cd ""
printf -v cmd '%q ' zsh -c "$cd_cmd && zsh -i"
lxterminal --command="$cmd"
}
printf '%q'
求值为给定字符串的一个版本,当 eval
被 bash(或具有等效语义的任何 shell)编辑时,求值为原始文字值。
解释为什么这样做:
- 在上面,代码本身中包含的所有引号字符都是句法而非文字:我们依赖
printf %q
进行 所有 引用和转义。这是最佳实践方法:使用文字引号意味着正在生成的数据中的文字能够转义这些引号。 - 运行 shell 指令,例如
&&
到 shell 引用将使它们成为文字数据。因此,当我们将其作为参数传递给-c
时,我们 希望&&
是文字数据而不是语法,但在处理时不是文字数据远程 shell -- 这就是为什么它只出现在 last 引用传递中的原因。