搜索文件(grep / awk)以获取2个回车符/换行符

时间:2015-09-24 22:11:43

标签: bash awk grep

我正在尝试编写一个脚本,它只会计算文件中\ r \ n \ r \ n的出现次数。 (以vim二进制模式打开示例文件会在适当的位置显示^ M字符,并且新行仍然作为换行符读取。)

无论如何,我知道有很多解决方案,但它们似乎没有让我得到我想要的东西。

e.g。 awk -e '/\r/,/\r/!d'或使用$'\n'作为grep语句的一部分。

然而,这些似乎都没有产生我需要的东西。我用grep的“技巧”找不到\r\n\r\n模式,因为它只扩展了一个变量。 awk解决方案是贪婪的,因此让我获得比我想要/需要更多的行。

将grep切换为二进制/ Perl / no-newline模式似乎更接近我想要的, 例如grep -UPzo '\x0D',但我真正想要的是grep -UPzo '\x0D\x00\x0D\x00',它不会产生我想要的输出。

这似乎是一项如此简单的任务。

1 个答案:

答案 0 :(得分:3)

默认情况下,awk将\n视为记录分隔符。这使得计算\r\n\r\n非常困难。如果我们选择其他记录分隔符,比如说一个字母,那么我们可以很容易地计算出这种组合的外观。因此:

awk '{n+=gsub("\r\n\r\n", "")} END{print n}' RS='a' file

此处,gsub返回所做的替换次数。这些是相加的,在达到file结束后,我们打印总数。

实施例

在这里,我们使用bash的$'...'构造来显式添加换行符和换行符:

$ echo -n $'\r\n\r\n\r\n\r\na' | awk '{n+=gsub("\r\n\r\n", "")} END{print n}' RS='a' 
2

替代解决方案(GNU awk)

我们可以告诉它将\r\n\r\n视为记录分隔符,然后返回记录数的计数(减1):

 cat file <(echo 1) | awk 'END{print NR-1;}' RS='\r\n\r\n'

在awk中,RS是记录分隔符,NR是记录数的计数。由于我们使用的是多字符记录分隔符,因此需要使用GNU awk。

如果文件以\r\n\r\n结尾,则上述内容将被关闭。为避免这种情况,echo -n 1语句用于确保文件中最后\r\n\r\n后始终至少有一个字符。

实施例

在这里,我们使用bash的$'...'构造来显式添加换行符和换行符:

$ echo -n $'abc\r\n\r\n' | cat - <(echo 1) | awk 'END{print NR-1;}' RS='\r\n\r\n'
1
$ echo -n $'abc\r\n\r\ndef' | cat - <(echo 1) | awk 'END{print NR-1;}' RS='\r\n\r\n'
1
$ echo -n $'\r\n\r\n\r\n\r\n' | cat - <(echo 1) | awk 'END{print NR-1;}' RS='\r\n\r\n'
2
$ echo -n $'1\r\n\r\n2\r\n\r\n3' | cat - <(echo 1) | awk 'END{print NR-1;}' RS='\r\n\r\n'
2