在 bash 中使用 printf 在转义 ' 或 "(单引号或双引号)中转义 \e

Escaping \e in escaped ' or " (single or double) quotes with printf in bash

我正在编写一个 shell 脚本,每次我得到一台新机器时,它都会按照我喜欢的方式设置我的 osx 机器。我真正喜欢的一种命令行糖是“up arrow bash history search”。正如询问 ubuntu post 所说,添加行:

bind '"\e[A":history-search-backward'

我的 ~/.bashrc 会为我做这件事,但是,我想从我的脚本中自动完成...

为了实现它,我使用 printf 取得了最大的成功,但我需要在绑定后立即转义引号和转义序列 ('"\e),例如:

printf "bind \'\"\e[A\":history-search-backward\'" >> ~/.bashrc

但在那个例子中,转义序列没有转义,所以在我的 ~/.bashrc 中,我得到了这一行:

bind '"^[[A":history-search-backward'

我尝试了很多不同的 quoting/escaping/interpolation 组合,但收效甚微,有没有人有一些字符转义 foo 可以实现这个,或者甚至只是解释为什么这不起作用,google 在地面上特别薄,尤其是在 \e 转义周围。

使用此处文档:

cat <<'EOF' >>~/.bashrc
bind '"\e[A":history-search-backward'
EOF

EOF 两边的引号表示 here-document 的内容将被视为单引号字符串,因此 $ 将按字面意思处理,而不是作为变量前缀。这在这个特定的字符串中无关紧要,但在更一般的应用程序中可能是这样。

此处引用的文档是最简单的方法(如其他人的评论和 Barmar 的回答),但如果您真的想使用 printf,有几种方法可以做到那。在进入主要问题之前,有两个次要问题:您不需要对字符串中的单引号进行转义,并且 do 需要添加一个换行符 (\n) 最后(与 echo 不同,printf 不会自动添加)。

你当前命令的最大问题是你将你想要的字符串放在 printf 的第一个参数中,它把它当作格式字符串——除其他外,这意味着它解释其中的转义序列。在 shell 已经解释了它们之后。因为转义解释有两个阶段,你需要quadruple the escape你想在最后的字符串中结束:

printf "bind '\"\\e[A\":history-search-backward'\n"

或者,您可以将字符串放在 printf 的第二个参数中,并使用仅按字面意义包含它的格式字符串(%s 指令) 而无需 额外级别的转义解释:

printf '%s\n' "bind '\"\e[A\":history-search-backward'"

请注意,\n 必须在格式字符串中,因此它会被转换为实际的换行符。

或者您可以只使用此处引用的文档。