为什么 grep 不能显示包含 ^M(必须是 unix 新行)字符的找到的行?

Why can't grep display found lines if they contain ^M (must be unix new lines) characters?

我的 vimrc 文件中有宏行,例如:

let @i = "oif (^[a) {^[a^M}^[k0f)"

其中"^["和"^M"是在插入模式下通过"Ctrl-V"输入的字符,所以它们必须是Escape和Newline (我用的是Linux,而Vim配置为使用'\n'换行符,但这个字符在vimrc文件中到底是什么我不知道).

当我用 grep -B 2 'i = "' ~/.vimrc 搜索这样一行时,我看到一个完全损坏的输出:

hi Comment cterm=none ctermbg=226 ctermfg=009 guibg=#ffff00 guifg=#ff0000

}0f)"i = "oif () {

虽然我想要:

hi Comment cterm=none ctermbg=226 ctermfg=009 guibg=#ffff00 guifg=#ff0000

let @i = "oif (^[a) {^[a^M}^[k0f)"

或者至少是类似的东西,第三行以 let @i 开头。但是我看到 }0f)"i = "oif () { 并且没有 let @i 的迹象。

我试着调查了一下,发现它可以正常工作,直到该行有“^M”字符。

谁能告诉我如何修复它,或者至少解释一下那里发生了什么?

grep 正在发送 Escape 序列 (例如 ^[a^[k;参见 Amadan 的评论 以下) 和 control character (^M) 到终端,他们弄乱了输出,这是 当被其他命令过滤时显示:

grep -B 2 'i = "' ~/.vimrc | cat -v

grep -B 2 'i = "' ~/.vimrc | less

这就是 cat's man page 关于 -v

的说法
-v, --show-nonprinting
    use ^ and M- notation, except for LFD and TAB

这也是从 less's man page 中截取的相关内容:

Control and binary characters are displayed in standout (reverse video).  Each
such character is displayed in caret notation if possible (e.g. ^A for control-
A).  Caret notation is used only if inverting the 0100 bit results in a normal
printable character.  Otherwise, the character is displayed as a hex number in
angle brackets.

这些控制序列通常用于发送不可打印的字符 到终端,允许用户通过添加自定义终端输出 (前景和背景)颜色,四处移动光标等。

无效的转义序列,如 ^[a^[k 将被忽略,因此您将获得 如果宏是这样定义的,同样的问题:

let @i = "oif () {^M}0f)"

^M马车 return 它告诉终端 在打印其余部分之前将光标移动到行首 输出(这将覆盖之前的输出)。这类似于键入 0 在正常模式下,按R然后输入

}0f)"

自己在:

let @i = "oif () {^M}0f)"

希望这个回答对您有所帮助。