egrep匹配行尾失败的问题分析

前言

在做一个代码审查的小工具的时候,需要检测代码中是否有行尾空格,因此就想通过egrep来进行字符串匹配,匹配命令如下:

egrep ' +$' FILE

发现,有些文件明明行尾是有空格的,但是却就是匹配不到,本篇博客就是记录如何排查和解决该问题的。

排除中文影响

最开始的时候,怀疑是由于中文编码格式造成的问题,因此对于能够匹配成功的文件,做了以下测试:

$ file *.txt
ANSI.txt:   ISO-8859 text
UCS2BE.txt: Big-endian UTF-16 Unicode text
UCS2LE.txt: Little-endian UTF-16 Unicode text
UTF8.txt:   UTF-8 Unicode text
$ egrep ' +$' *.txt -l
ANSI.txt
UCS2BE.txt
UCS2LE.txt
UTF8.txt

即,egrep对于各种编码格式已经做了考虑,问题不在编码格式上。

寻找差异

通过file命令,我们发现了一下差异:

$ file *.txt
ANSI.txt:   ISO-8859 text
bad.txt:    UTF-8 Unicode text, with CRLF line terminators

注意,对于无法匹配成功的文件结束符是CRLF,而对于可以匹配成功的文件结束符则没有明确说明(通过Notepad++确认是LF)。

我们通过dos2unix命令,将文件转为unix格式后,发现可以使用egrep正确匹配:

$ dos2unix bad.txt 
dos2unix: converting file bad.txt to Unix format ...
$ file bad.txt 
bad.txt: UTF-8 Unicode text
$ egrep ' +$' bad.txt -l
bad.txt

因此,问题确认就是egrep在处理CRLF结尾的文件时无法正确匹配行尾。

解决方案

网上找到的资料也是先通过dos2unix对文件转换格式后,再进行匹配。但是在进行代码审查的过程是不能修改源文件的。

因此,我按照以下的思路来解决这个问题:
1. 将源文件进行dos2unix转码后,直接输出到标准输出上
2. 通过管道,对上面输出的内容进行egrep匹配

我首先查看dos2unix命令是否有输出到标准输出的参数,发现有-n参数,使用说明如下:

# -n, --newfile         write to new file
#   infile              original file in new file mode
#   outfile             output file in new file mode
# e.g.: Convert a.txt and write to e.txt.
dos2unix -n a.txt e.txt

这里有一个问题,就是每次转换都需要一个临时文件,那么就存在:临时文件冲突以及需要删除临时文件的问题。而并没有直接输出结果到标准输出上的参数。

迂回一下,我发现dos2unix命令是可以接受管道输入的,即可以有以下的命令:

cat bad.txt | dos2unix

结合上面的egrep,最终的命令如下:

cat bad.txt | dos2unix | egrep ' +$'

而判断是否匹配成功,则可以通过$?来进行判断:

echo $?

猜你喜欢

转载自blog.csdn.net/nfer_cn/article/details/49154319