如何在以各种方式引用时正确转义 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 引用传递中的原因。