Regex grep匹配,但如果行以dos ^M结尾,则不打印
我需要在多个文件中搜索一个模式,如果找到显示文件,线和由几个额外字符包围的模式。我的问题是,如果匹配模式的行以^M(CRLF)结尾,grep将打印一个空行 创建这样的文件,第一行“a^M”,第二行“a”,第三行空行,第四行“a”(后面不跟新行) 在找到并显示模式后,无需尝试匹配几个字符:Regex grep匹配,但如果行以dos ^M结尾,则不打印,regex,bash,grep,Regex,Bash,Grep,我需要在多个文件中搜索一个模式,如果找到显示文件,线和由几个额外字符包围的模式。我的问题是,如果匹配模式的行以^M(CRLF)结尾,grep将打印一个空行 创建这样的文件,第一行“a^M”,第二行“a”,第三行空行,第四行“a”(后面不跟新行) 在找到并显示模式后,无需尝试匹配几个字符: # grep -srnoEiI ".{0,2}a" * 1:a 2:a 4:a 如果我尝试匹配图案末尾的任何字符,它将打印一个空行,而不是以CRLF结尾的第一行: # grep -srnoEiI ".{0,2
# grep -srnoEiI ".{0,2}a" *
1:a
2:a
4:a
如果我尝试匹配图案末尾的任何字符,它将打印一个空行,而不是以CRLF结尾的第一行:
# grep -srnoEiI ".{0,2}a.{0,2}" *
2:a
4:a
我如何才能将此更改为按预期操作
另外,我想修复这个grep,但我会接受其他解决方案,例如在awk中
编辑:
根据下面的答案,我选择剥离\r并强制grep将颜色管道传输到tr:
grep --color=always -srnoEiI ".{0,2}a.{0,2}" * | tr -d '\r'
或
这两种方法都可以:查找模式,查看行是否以回车结束,打印行号和行。对于sed,行号在它自己的行上,因此我们必须用冒号连接两个连续的行
或
这两种方法都可以:查找模式,查看行是否以回车结束,打印行号和行。对于sed,行号在它自己的行上,因此我们必须用冒号连接两个连续的行。这里有一个更简单的情况重现您的问题:
# 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
这里有一个更简单的例子再现了您的问题:
# 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
还有两种方法:
使用将dos样式的行尾转换为unix样式:
dos2unix myfile.txt
或删除CR字符,然后通过管道连接到grep:
$ tr -d '\r' < myfile.txt | grep -srnoEiI ".{0,2}a.{0,2}"
1:a
2:a
4:a
$
$tr-d'\r'
注意:可能需要在您使用的任何操作系统上安装dos2unix
。非常可能。还有两种方法:
使用将dos样式的行尾转换为unix样式:
dos2unix myfile.txt
或删除CR字符,然后通过管道连接到grep:
$ tr -d '\r' < myfile.txt | grep -srnoEiI ".{0,2}a.{0,2}"
1:a
2:a
4:a
$
$tr-d'\r'
注意:可能需要在您使用的任何操作系统上安装
dos2unix
。非常有可能。您可以使用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
您可以使用
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
您可以将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$
您可以将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$
使用
dos2unix
实用程序是否可以将CRLF结尾转换为LF?您的预期输出是什么?@digitaltrampa,不,我正在搜索+4GB的源代码文件,我不想全部触摸和更改。@anubhava上述第一个和第二个grep示例中的输出应该是相同的,即您的“| cat-vte”正在生成预期的输出。感谢您的回答,在多次阅读您的问题后,我意识到您的问题,因此发布了一个答案。使用dos2unix
实用程序是否可以将CRLF结尾转换为LF?您的预期输出是什么?@digitaltrama,不,我正在搜索+4GB的源代码文件,我不想触摸和更改它们。@anubhava在上面的第一个和第二个grep示例中,输出应该是相同的,您的“| cat-vte”正在生成预期的输出。感谢您的回答,在阅读了您的问题几次之后,我意识到您在问什么,因此发布了一个答案。