我需要在多个文件中搜索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'
答案 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$