我有一个包含一些行的文件,例如
x
y
当我跑步时
grep -E "x$" filename.txt
它不匹配任何东西。正如 vi^M
在大多数行末尾显示的那样,我猜问题是混合了 Dos 和 Unix 换行符以及 grep 自动检测格式。
我试过
grep --color=never -E "x.$" filename.txt
匹配\r
行末尾的额外内容并且它可以工作,但是它会打印单个字符\r
,因此在--color=always
添加终端控制字符时会中断。
我需要的是一个选项,将\r\n$
和\n
与相匹配$
。
示例文件的十六进制转储:
00000000 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 |xxxxxxxxxxxxxxxx| 00000010 78 78 78 78 78 78 78 78 78 78 780d 0a790a |xxxxxxxxxxx..y.|
您可以看到 DOS 行结束符和 unix 行结束符。打印该行时,的输出grep -E --color=always "x.$"
似乎为空grep -E --color=never "x.$"
,可能包含与 匹配的回车\r
符.
。
答案1
如果您使用 GNU grep
,则可以使用\s
PCRE 中的符号来匹配任何空白,因此\s*
将匹配 0 个或多个空白字符:
$ printf 'x\r\nxx\n' > file
$ grep --color=no -P 'x\s*$' file
xx
请注意,看起来像空行的内容实际上并不是空的,它\r
导致终端向后移动并覆盖x
*。您可以通过以下方式查看它的实际效果od
:
$ grep -P 'x\s*$' file | od -c
0000000 x \r \n x x \n
0000006
如果您没有 GNU ,您可以以相同的方式grep
使用 POSIX 字符类:[:space:]
$ grep 'x[[:space:]]*$' file | od -c
0000000 x \r \n x x \n
0000006
使用标准工具(如或 )\r
也可以轻松删除:tr
sed
$ tr -d '\r' < file | grep 'x$'
$ tr -d '\r' < file | grep 'x$'
x
xx
$ sed 's/\r//' file | grep 'x$'
x
xx
* 请注意,正如所解释的@dave_thompson-085,这只会发生,因为我有grep
别名,grep --color=auto
这意味着颜色代码打印在 周围x
,这就是导致x
被覆盖的原因,因为它\r
导致终端向后移动光标,因此x
随后被非打印覆盖颜色转义码。
答案2
我需要的是一个选项,以匹配 \r\n$ 和 \nwith$`。
你可以这样做:
$ grep 'x^M\?$' infile
要键入“^M”,您应该按住该ctrl
键,按V
,然后ctrl
再次按M
并按命令行。 A^M
将会出现,编码一个carriage return
字符。
请理解 grep 的输出将仍然包含一个carriage return
.该字符告诉终端将打印位置返回到行首并从那里继续打印。这可能会导致奇怪的后果。
我建议使用 清理文件dos2unix
。
dos2unix infile >clean.infile
或者甚至(仅作为示例,请不要cat该文件,dos2unix能够直接读取它):
cat infile | dos2unix | grep 'x$'