zsh:命令替换、正确的引号和反斜杠(再次)

zsh: command substitution, proper quoting and backslash (again)

(注意:这是我发帖 的后续问题,但现在更复杂了)。

我有一个函数_iwpath_helper,它向标准输出输出一条路径,其中可能包含spaces。为了便于讨论,我们假设 _iwpath_helper 总是 return 是一个常量文本,例如

function _iwpath_helper
{
    echo "home/rovf/my directory with spaces"
} 

我还有一个函数 quote_stripped 需要一个参数,如果这个参数被引号括起来,它会删除它们并 return 留下剩余的文本。如果参数没有被引号包围,则 return 保持不变。这是它的定义:

function quote_stripped 
{
    echo ${1//[\"\']/}
}

现在我按以下方式组合这两个函数:

target=$(quote_stripped "${(q)$(_iwpath_helper)}")

(当然,'quote_stripped' 在这个玩具示例中是不必要的,因为 _iwpath_helper 在这里不是 return 引号分隔的路径,但在实际应用程序中,它有时会)。

现在的问题是变量 target 包含一个 real 反斜杠字符,即如果我做一个

echo +++$target+++

明白了

+++home/rovf/my\ directory\ with\ spaces

如果我尝试

cd $target

我的系统出现错误消息,目录

home/rovf/my/ directory/ with/ spaces

不会存在。

(如果您想知道正斜杠的来源:我在 Cygwin 上使用 运行,我猜在这种情况下 cd 命令只是将反斜杠解释为正斜杠,以便更好地适应Windows 环境)。

我猜物理上出现在变量 target 中的反斜杠是由我应用于 $(_iwpath_helper) 的 (q) 扩展标志引起的。我现在的问题是我不能简单地删除 (q),因为没有它,函数 quote_stripped 将仅在参数 $1 上获取字符串的第一部分,直到第一个 space (/home/rovf/my).

我怎样才能正确地写这个?

我认为您只是想避免尝试手动删除引号,并使用 (Q) 扩展标志。比较:

% v="a b c d"
% echo "$v"
a b c d
% echo "${(q)v}"
a\ b\ c\ d
% echo "${(Q)${(q)v}}"
a b c d

chepner 是对的:我试图取消引用字符串的方式很愚蠢(我在 "Bourne Shell way" 中想得太多了),我应该使用 (Q) 标志。

这是我的解决方案:

target="${(Q)$(_iwpath_helper)}"

不再需要 quote_stripped 功能....