为什么Linux grep没有为换行提供正确的计数?

时间:2014-01-05 01:07:28

标签: linux bash shell unix grep

在Ubuntu 10.04.4 LTS上,我做了以下小测试并得到了一个令人惊讶的结果:

首先,我创建了一个包含5行的文件,并将其命名为a.txt

echo -e "1\n2\n3\n4\n5" > a.txt
$ cat a.txt
1
2
3
4
5

然后我运行wc来计算行数

$ wc -l a.txt
5 a.txt

但是,当我运行grep来计算包含换行符的行数时,我得到了一个我不理解的答案:

$ grep -c -P '\n' a.txt
3

我的问题是:grep如何获得此号码?不应该是4?

4 个答案:

答案 0 :(得分:3)

Grep无法看到换行符。它搜索内联模式。 请考虑使用grep -c -P '$' a.txt来匹配每行的结尾。

答案 1 :(得分:3)

请阅读精细手册!

 seq 1 5  | wc -l
 5

 seq 1 5  | grep -ac $'\n'
 5

我不明白问题在哪里!?

 seq 1 5  | hd
 00000000  31 0a 32 0a 33 0a 34 0a  35 0a                    |1.2.3.4.5.|

说明:

  • -a切换告诉grep二进制模式打开文件。 IE 不关心文本格式

  • $'\n'语法由bash自己解决,运行grep之前解析。这样做可以将控制字符作为参数传递给下的任何命令。

答案 2 :(得分:2)

换行符不是行的一部分。 grep使用换行符作为记录分隔符,并将其从行中删除,以便$的模式按预期工作。例如,要搜索以foo结尾的行,您可以使用模式foo$代替foo\n$。这将非常不方便。

所以grep -c -P '\n' a.txt应该给你0.如果你得到3,这听起来很奇怪,但也许可以解释man grep中的高度实验性评论:

   -P, --perl-regexp
          Interpret  PATTERN  as  a  Perl  regular  expression  (PCRE, see
          below).  This is highly experimental and grep  -P  may  warn  of
          unimplemented features.

我在Debian / Wheezy,这比Ubuntu 10.04更新。如果今天-P是“高度实验性的”,那么想象它在旧系统中是错误的并不难。这只是猜测。

要计算换行数,请使用wc -l,而不是grep -c黑客。

有趣的是,顺便说一下:

$ printf hello >> a.txt 
$ wc -l a.txt 
5 a.txt
$ grep -c '' a.txt 
6

也就是说,printf不会打印换行符,因此在我们向a.txt追加“hello”后,文件末尾不会有换行符。因此wc -l计算换行符,而不是“行”,grep ''(空字符串)匹配所有行。

答案 3 :(得分:0)

我想你想用

$ grep -c -P "." a.txt
5
$ echo "6" >> a.txt
$ grep -c -P "." a.txt
6
$ cat a.txt
1
2
3
4
5
6