grep 有很多文件,其中包含很多行?

grep 有很多文件,其中包含很多行?

想象一下我们有很多巨大的(30000 行)文件:a.2014-05-06、a.2014-05-07、a.2014-05-08 等等。

我知道我们可以使用以下命令 grep 一行单词:

grep "word" a.*

首先,我想这会打开每个文件并在打开第二个文件来搜索单词之前关闭它?这是否有效,如果没有,是否有更有效的方法?

二 如何确定我们在哪个文件中找到该单词?例如:
如果 a.2014-05-06 有:

a
bx
.
.

a.2014-05-07:

by
.
.

a.2014-05-08:

c
.
.

我们执行以下操作:

grep "b" a.*

输出将是:

bx
by

我想要这样的输出:

bx  a.2014-05-06
by  a.2014-05-07

答案1

man grep:

       -H, --with-filename
           Print the file name for each match.  This is the default when there is
           more than one file to search.

它将首先打印文件名,然后打印匹配项;这不是您在示例结果中显示的内容。但如果这不会造成问题,那么它又快又容易。

由于它是多个输入的默认值,因此将其与通配符一起使用(如您的示例中所示)会导致:

$ grep "b" a.*
a.2014-05-06:bx
a.2014-05-07:by

您没有提到您正在使用哪种类型的 Unix/Linux,但该-H选项在大多数实现中都可用,尽管它不在 POSIX 规范中。

答案2

要搜索磁盘而不打开每个文件:

dd if=/dev/${disk_device} |
grep -b 'some regex'

事实上,我更喜欢这个:

sudo cat /dev/${some_disk} |
tr -c '[:print:][:space:]' '\n\n' |
grep -b 'some regex'

-b选项将为您提供所有匹配的字节偏移量。之后您可以使用文件系统检查这些偏移处存在哪些文件。

在第二种形式中,您可以避免grep抱怨二进制文件类型通过提供换行符来代替不相关的数据,自动加快搜索速度。

PS - 如果您的文件系统可以进行碎片整理,那么首先这样做可能是个好主意。

答案3

首先,我想这会打开每个文件并在打开第二个文件来搜索单词之前关闭它?这是否有效,如果没有,是否有更有效的方法?

是的,grep 将依次打开并搜索每个文件。在大多数设置中,这是最有效的方法。除非正则表达式极其复杂,否则此任务绝对受 I/O 限制,即性能瓶颈是从磁盘读取,并且您的 CPU 不会受到负担。

在某些设置中,I/O 可以并行化;例如,如果您有 RAID-1 或​​ RAID-0 配置,则可以并行读取 RAID 阵列中的两个(或多个)组件,这将节省时间。如果您有这样的设置,您可以调用类似的工具GNU 并行调用 grep 的两个实例(有关命令示例,请参阅手册)。在大多数设置中,并行调用 grep 的两个实例会更慢,因为磁盘头将在两个实例访问的文件之间不断切换(对于 SSD,并行调用两个实例通常不会导致严重的速度减慢,但它会赢得也不能更快)。

如果在命令行上传递多个文件,grep 会在每次匹配之前输出文件名,格式如下

path/to/file:line containing a match

如果您使用通配符模式或某些其他形式生成文件名,并且即使在恰好有一个匹配文件的情况下也希望显示文件名,请告诉 grep 搜索空文件名空设备以及。

grep REGEX /dev/null *.txt

grep -H REGEX *.txt类似,但 using/dev/null具有额外的好处,即使匹配文件列表为空,它也可以无缝工作,而grep -H REGEX从标准输入读取。)

答案4

grep在处理大型(或许多)文件时要记住另外两件事:

  1. 如果您正在搜索固定字符串而不是模式,请将选项添加-Fgrep,它将极大地加快您的搜索速度(请参阅来源

  2. 如果您知道您实际上正在寻找一个单词,即您的搜索模式以非单词字符或行的开头/结尾为界,则添加该-w选项。我认为这会加快搜索速度。

相关内容