想象一下我们有很多巨大的(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
在处理大型(或许多)文件时要记住另外两件事:
如果您正在搜索固定字符串而不是模式,请将选项添加
-F
到grep
,它将极大地加快您的搜索速度(请参阅来源)如果您知道您实际上正在寻找一个单词,即您的搜索模式以非单词字符或行的开头/结尾为界,则添加该
-w
选项。我认为这会加快搜索速度。