前言
首先,你的命令有几个缺陷,在某些情况下会失败:
-
它不能处理由非ascii字符(如重音字母)组成的单词,因为它们被过滤
strings
是的。不过,你可能并不想听到这样的话。
-
如果单词是孤立的,它将丢失少于4个字符的单词。你应该用
strings -n1
一个通用的解决方案。
-
当多个单词属于同一行文本时,它将丢失单词,因为
grep -c
数数线条,而不是文字。
Android实现的问题
grep
(从Android 8.1开始):
-
在android上,你必须使用
grep -E 'word1|word2|...|wordN'
而不是
grep -F -e word1 -e word2 .. -e wordN
相当于,但通常要快得多。这是因为android 8中存在一个错误,使得后者无法正确计算。
-
在android上,我不会只使用
grep -a
但是
grep -za
. 在linux上,gnu grep将二进制文件中的nul(0)字符视为行尾,并且
-z
选项不仅无用,而且不可取,因为输出行也将以nul而不是换行符结束。但是android版本的表现有所不同:nul字符需要显式地作为换行符处理,否则后面的内容将被忽略;碰巧换行符仍然是用传统换行符输出的。
限制的输出
串
通过设置
-n
选择权
串
到你要找的最小单词的大小。例如,如果您要查找的单词都不少于7个字符,请使用
strings -n7
. 因此,您将降低进程间通信,并且
格雷普
不会费心搜索那些显然不符合模式的行。
摆脱
串
串
有点贵,可能没有什么好处(这取决于被过滤掉的二进制字符的数量-ymmv,请参阅下一节中的注释),甚至是有害的(请参阅前言)。你可以通过以下方式摆脱它:
grep -F -a -o -e word1 -e word 2 ... -e wordN /path/to/binary_file \
| wc -l
因为前面提到的android的问题
格雷普
,这是Android的版本:
grep -z -a -o -E 'word1|word2|...|wordN' /path/to/binary_file \
| wc -l
记住,使用
grep | wc
是强制性的,因为
格雷普-C
不计算字数,只计算行数。这就是为什么
格雷普-C
在你看来要快一点,因为一旦找到一个词,
格雷普
计数+1并继续下一个输入行,可能在当前行上缺少其他单词。
并行化
根据核的数量,您还可以通过并行化
格雷普
学生:
( grep -F -a -o -e word1 -e word2 /path/to/binary_file &
grep -F -a -o -e word3 -e word4 /path/to/binary_file
) | wc -l
因为前面提到的android的问题
格雷普
,这是Android的版本:
( grep -z -a -o -E 'word1|word2' /path/to/binary_file &
grep -z -a -o -E 'word3|word4' /path/to/binary_file
) | wc -l
在这里,我假设最密集的处理是由
串
和
格雷普
由于它们的过滤作用
wc
他的工作是次要的。根据搜索模式的不同,情况可能不同。同样,如果
串
在过滤掉二进制文件方面做得很好,最好把它作为第一条指令。YMMV公司。
使用
tr
而不是
串
串
可能会过滤掉大量不必要的(非ascii)字符,这确实有帮助
格雷普
处理更少的数据。你可以通过过滤掉不属于你要找的单词的每个字符来做得更进一步。例如,如果查找“word1”、“word2”和“word3”,则可以筛选出不是w、o、r、d、1、2、3的所有字符。
如果您有权访问
tr公司
命令行工具,使用它而不是
串
:
tr -c -s 'word123' '\n' < /path/to/binary_file \
| grep -F -o -e word1 -e word2 -e word3 \
| wc -l
因为前面提到的android的问题
格雷普
,这是Android的版本:
tr -c -s 'word123' '\n' < /path/to/binary_file \
| grep -E -o 'word1|word2|word3' \
| wc -l
(注意
tr公司
不适用于非ascii多字节字符,但因为您正在使用
串
在ascii模式下,您已经不关心这个了)
标杆管理
下面是在一个24mb的声音文件上做的一些测试;这个平台是我的android 8.1octacore手机。根据您的输入文件、搜索字符串和核心数,您显然会得到其他结果,但这会让您了解可能的速度改进。
# Your original command (fixed)
$ time strings -n1 test | grep -E 'A|B|C|D' -o | wc -l
403380
0m18.93s real 0m10.05s user 0m13.77s system
# grep alone
$ time grep -z -a -E 'A|B|C|D' -o test | wc -l
403380
0m07.03s real 0m05.26s user 0m00.04s system
# Parallelized grep (x2)
$ time ( grep -z -a -E 'A|B' -o test &
grep -z -a -E 'C|D' -o test
) | wc -l
403380
0m03.56s real 0m03.12s user 0m00.03s system
# Parallelized grep -F (x4 - one per string to search)
$ time ( grep -z -a -F A -o test &
grep -z -a -F B -o test &
grep -z -a -F C -o test &
grep -z -a -F D -o test
) | wc -l
403380
0m01.04s real 0m01.88s user 0m00.05s system
# tr instead of string
$ time tr -c -s 'ABCD' '\n' < test | grep -E 'A|B|C|D' -o | wc -l
403380
0m01.60s real 0m01.27s user 0m01.41s system
# Parallelized tr + grep (x2)
$ time ( tr -c -s 'AB' '\n' < test | grep -E 'A|B' -o &
tr -c -s 'CD' '\n' < test | grep -E 'C|D' -o
) | wc -l
403380
0m00.95s real 0m01.23s user 0m02.20s system
如您所见,在这些测试条件下,与
串
最后一个(和
tr公司
并并行化)。