如果行结束在dos ^ M,则grep匹配但不打印

时间:2014-05-13 18:11:28

标签: regex bash grep

我需要在多个文件中搜索PATTERN,如果找到则会显示由一些额外字符包围的文件,行和PATTERN。我的问题是,如果匹配PATTERN的行以^ M(CRLF)结束,则grep会打印一个空行。

创建一个这样的文件,第一行“a ^ M”,第二行“a”,第三行空行,第四行“a”(后面没有新行)。

a^M
a

a

在PATTERN发现并显示所有匹配项后,不试图匹配几个字符:

# grep -srnoEiI ".{0,2}a" *
1:a
2:a
4:a

如果我尝试匹配PATTERN末尾的任何字符,它会打印一个空行而不是第一行,一行以CRLF结尾:

# grep -srnoEiI ".{0,2}a.{0,2}" *

2:a
4:a

如何更改此操作以按预期执行?

P.S。我想修复这个grep,但我会接受其他解决方案,例如在awk中。

修改

根据下面的答案,我选择剥离\ r并强制grep将颜色管道传输到tr:

grep --color=always -srnoEiI ".{0,2}a.{0,2}" * | tr -d '\r'

5 个答案:

答案 0 :(得分:2)

这是一个更简单的案例,可以重现您的问题:

# Output 
echo $'a\r' | grep -o "a"
# No output
echo $'a\r' | grep -o "a."

这是因为^M像常规字符一样匹配,并使你的终端覆盖其输出(这纯粹是装饰性的)。

您希望如何解决这个问题取决于您想要做什么。

# Show the output in hex format to ensure it's correct
$ echo $'a\r' | grep -o "a." | od -t x1 -c
0000000  61  0d  0a
      a  \r  \n

# Show the output in visually less ambiguous format
$ echo $'a\r' | grep -o "a." | cat -v
a^M

# Strip the carriage return
$ echo $'a\r' | grep -o "a." | tr -d '\r'
a

答案 1 :(得分:1)

awk -v pattern="a" '$0 ~ pattern && !/\r$/ {print NR ": " $0}' file

sed -n '/a/{/\r$/!{=;p}}' ~/tmp/srcfile | paste -d: - -

这两个都做:找到图案,查看线条是否在回车符中结束,打印行号和行。对于sed,行号是在它自己的行上,所以我们必须用冒号连接两个连续的行。

答案 2 :(得分:1)

还有几种方式:

使用dos2unix utility将dos样式行结尾转换为unix-style:

dos2unix myfile.txt

preprocess the file using tr删除CR字符,然后输送到grep:

$ tr -d '\r' < myfile.txt | grep -srnoEiI ".{0,2}a.{0,2}"
1:a
2:a
4:a
$

注意dos2unix可能需要安装在您使用的任何操作系统上。很可能是tr will be available on any POSIX-compliant OS

答案 3 :(得分:1)

您可以使用pcregrep

pcregrep -n '.{0,2}a.{0,2}' inputfile

您的样本输入:

$ printf $'a\r\na\n\na\n' | pcregrep -n '.{0,2}a.{0,2}' 
1:a
2:a
4:a

答案 4 :(得分:1)

您可以将awk与自定义字段分隔符一起使用:

awk -F '[[:blank:]\r]' '/.{0,2}a.{0,2}/{print FILENAME, NR, $1}' OFS=':' file

<强>测试

你的grep命令:

grep -srnoEiI ".{0,2}a.{0,2}" file|cat -vte
file:1:a^M$
file:2:a$
file:4:a$

建议的awk命令:

awk -F '[[:blank:]\r]' '/.{0,2}a.{0,2}/{print FILENAME, NR, $1}' OFS=':' file|cat -vte
file:1:a$
file:2:a$
file:4:a$