grep --color=auto 在 ^M 处于彩色匹配中时中断

mx0*_*mx0 5 grep colors

我有 2 个类似的文件(dos.txt 和 unix.txt),其中的文本The quick brown fox jumps\n over the lazy dog.因行尾而异。当我在行尾搜索单词时,dos.txt 的输出为空:

$ grep -E 'jumps^M?$' dos.txt unix.txt

unix.txt:The quick brown fox jumps
Run Code Online (Sandbox Code Playgroud)

Grep 找到了一些东西,但没有打印出来。grep 的实际输出如下所示:

$ grep -E --color=always 'jumps^M?$' dos.txt unix.txt | cat -v
^[[35m^[[Kdos.txt^[[m^[[K^[[36m^[[K:^[[m^[[KThe ... ^[[01;31m^[[Kjumps^M^[[m^[[K
^[[35m^[[Kunix.txt^[[m^[[K^[[36m^[[K:^[[m^[[KThe ... ^[[01;31m^[[Kjumps^[[m^[[K
Run Code Online (Sandbox Code Playgroud)

所以看起来唯一的区别是 ^M 在彩色输出里面,它会导致整行消失。我该如何解决这个问题(不使用 dos2unix 或类似工具转换 dos 文件)?

mx0*_*mx0 11

在搜索^[[K转义序列后,阅读了一半关于VT100 终端的书并检查man grep我发现将环境变量设置GREP_COLORS

GREP_COLORS=ne
Run Code Online (Sandbox Code Playgroud)

提供所需的输出:

$ export GREP_COLORS=ne
$ grep -E --color=always 'jumps^M?$' dos.txt unix.txt
dos.txt:The quick brown fox jumps
unix.txt:The quick brown fox jumps

$ grep -E --color=always 'jumps^M?$' dos.txt unix.txt | cat -v
^[[35mdos.txt^[[m^[[36m:^[[mThe ... ^[[01;31mjumps^M^[[m
^[[35munix.txt^[[m^[[36m:^[[mThe ... ^[[01;31mjumps^[[m
Run Code Online (Sandbox Code Playgroud)

grep手册页:

ne     Boolean  value  that prevents clearing to the
       end of line using Erase in Line (EL) to Right
       (\33[K)  each  time  a  colorized  item ends.
       This is needed on terminals on  which  EL  is
       not  supported.   It  is  otherwise useful on
       terminals  for  which  the   back_color_erase
       (bce)  boolean  terminfo  capability does not
       apply, when the chosen  highlight  colors  do
       not  affect the background, or when EL is too
       slow or causes too much flicker.  The default
       is false (i.e., the capability is omitted).
Run Code Online (Sandbox Code Playgroud)

在我的情况下,即使我将高亮颜色设置为改变背景的东西,它也能很好地工作:

export GREP_COLORS="ne:mt=41;38"
Run Code Online (Sandbox Code Playgroud)

现在有趣的问题是为什么^[[K会产生这个空行。

字符^M表示不进入下一行的回车:

$ echo -e "start^Mend"
endrt
Run Code Online (Sandbox Code Playgroud)

^[[K 清除从光标到右侧的行,然后写入行的其余部分:

$ echo -e "start\033[Kend"
startend
Run Code Online (Sandbox Code Playgroud)

但是,当您^M^[[K删除内容之前放置时:

$ echo -e "start^M\033[Kend"
end
Run Code Online (Sandbox Code Playgroud)

写完开始光标到行首然后^[[K删除所有内容并写入行的其余部分。在grep输出的情况下,第一行将所有内容写入单词跳转,然后返回到行首^M,写入无害^[[m序列^J,然后转到新行。这就是为什么^[[K^M清除整行之后。