为什么 grep 和 Notepad++ 产生不同的结果?

use*_*312 22 grep

我有一个包含 6500 行和 2 列的数据文件:

1ES9 0.927536231884058 
1ET1 1.0 
1EU1 0.8915343915343915
... ... ...
Run Code Online (Sandbox Code Playgroud)

我想计算文件中 1.0 的出现次数。

我使用了以下grep命令,输出为 1001:

grep -o '1.0' data_file.txt | wc -l
Run Code Online (Sandbox Code Playgroud)

然后,我在windows 10下执行Notepad++的Find->Count工具。它给出了144。

为什么与 不同grep

Ste*_*itt 60

grep默认使用正则表达式,\xe2\x80\x9c1.0\xe2\x80\x9d 是匹配 \xe2\x80\x9c1\xe2\x80\x9d 后跟任何字符的正则表达式,后跟 \xe2\x80\x9c0 \xe2\x80\x9d。在您的示例中,该行

\n
1EU1 0.8915343915343915\n
Run Code Online (Sandbox Code Playgroud)\n

将产生 \xe2\x80\x9c1 0\xe2\x80\x9d 的匹配。

\n

要准确计算 \xe2\x80\x9c1.0\xe2\x80\x9d 的出现次数,您应该要求grep搜索固定字符串:

\n
grep -Fo 1.0 data_file.txt | wc -l\n
Run Code Online (Sandbox Code Playgroud)\n

或 \xe2\x80\x9cescape\xe2\x80\x9d 句点,以便它与句点匹配:

\n
grep -o \'1\\.0\' data_file.txt | wc -l\n
Run Code Online (Sandbox Code Playgroud)\n

如果您只想将 1.0 算作值,而不是子字符串(例如在 \xe2\x80\x9c11.002\xe2\x80\x9d 中),则应该要求grep仅匹配单词:

\n
grep -wo \'1\\.0\' data_file.txt | wc -l\n
Run Code Online (Sandbox Code Playgroud)\n

您不需要涉及wc其中任何一个,因为您只对每行一个匹配项感兴趣,并且grep可以计算行数:

\n
grep -cw \'1\\.0\' data_file.txt\n
Run Code Online (Sandbox Code Playgroud)\n

这仍然会匹配 \xe2\x80\x9c-1.0\xe2\x80\x9d,因为 \xe2\x80\x9c-\xe2\x80\x9d 是一个非单词字符;如果 \xe2\x80\x99 是一个问题,你可以扩展模式并停止寻找单词:

\n
grep -c \' 1\\.0$\' data_file.txt\n
Run Code Online (Sandbox Code Playgroud)\n

或者使用AWK等工具来匹配数值:

\n
awk \'$2+0 == 1 { c++ } END { print c }\' data_file.txt\n
Run Code Online (Sandbox Code Playgroud)\n

(添加 0 强制$2解释为数字)。

\n