bash 提示中使用反斜杠转义特殊字符进行字符串操作

bash 提示中使用反斜杠转义特殊字符进行字符串操作

我希望我的 bash 提示符\etc\defaultsPS1我处于/etc/defaults.

我尝试过这两种方法

PS1="$(echo "\w" | sed 's/\//\\/g')"
PS1="$(tmp="\w" && echo ${tmp//\//\\})"

但两者的结果都是/etc/defaults.

我觉得很奇怪,因为两者

echo $PWD | sed 's/\//\\/g'
tmp=$PWD && echo ${tmp//\//\\}

打印\etc\defaults

答案1

不管我们如何看待用反斜杠替换斜杠,这实际上是一个有趣的引用地狱问题。一个会提出其他类似结构的人。

如果你PS1包含$(echo "\w" | sed 's/\//\\/g'),会发生什么第一的Bash 处理它以进行提示转义,例如\w.所以echo "\w"变成echo "/etc/defaults",它基本上适用于好的路径名。但同时,它也把 变成了\\单一的\……所以你需要进入的PS1,是$(echo "\w" | sed -e 's/\\//\\\\/g')。或者使用双引号,与更多反斜杠相同: $(echo "\w" | sed -e "s/\\\\//\\\\\\\\/g").

然后就是问题任务PS1,在那里,您可能需要一个单引号字符串,它必须包含单引号,因此您需要将它们替换为'\''.它变成这样:

PS1='$(echo "\w" | sed -e '\''s/\\//\\\\/g'\'')'

这很尴尬,SE 语法荧光笔似乎没有正确遵循它,它将'\''s 之间的部分显示为未引用的部分。

但是......有更好的方法可以做到这一点。


这种\w替换有点可疑,因为在 shell 命令行上直接文本替换数据基本上会带来麻烦。如果路径是/tmp/quote"me,则直接替换将产生echo "/tmp/quote"me",并带有杂散引号。 Bash 实际上确实添加了反斜杠来转义引号,所以它变成了echo "/tmp/quote\"me",这是可以的。但它仍然很恶心,所以我宁愿避免它。如果转义与解析不匹配,则可能存在一个非常合理的命令注入问题。例如类似的echo '\w'不是工作,如果路径包含任何"$\,它会导致额外的反斜杠出现,并且如果它包含'. (与 SQL 注入类似的问题。)

此外,我们可以通过定义一个函数来运行该函数,从而从提示符本身中sed隐藏命令,从而摆脱引用地狱。s///顺便说一句,我们必须$PWD在这里使用,因为该函数本身不是提示的一部分,所以\w不起作用:

manglepath() {
    echo "$PWD" | sed 's/\//\\/g'
}
PS1='$(manglepath)\$ '

实际上我们应该能够使用${var//pattern/replacement}扩展而不是调用sed,并且我们可能应该使用printf代替echo

manglepath() {
    printf "%s\n" "${PWD//\//\\}"
}
PS1='$(manglepath)\$ '

答案2

PS1='$(echo "\w" | sed '\''s#/#\\\\#g'\'')'

这将导致 PS1$(echo "\w" | sed 's#/#\\\\#g')

相关内容