是否有一个命令可以在多个文件中搜索一个字符串,而该命令(可能由某个选项修改)不支持正则表达式?我希望这样可以避免正则表达式的速度,而且不必转义特殊字符。
(也很高兴知道在目录及其子目录中递归搜索的选项。)
如果文件是文本文件和字符串不包含换行符,您可以使用grep
与-F
(用于固定字符串)选项。
string='any /text\ *string* without newline (\n).'
find . -type f -exec grep -F -l -e "$string" {} +
列出包含包含该字符串的行的文本文件。
(此处限制为符号链接解析之前的常规文件)
一些grep
实现也可以处理非文本文件(比如那些包含 NUL、字节、带有超长行或字节序列的文件,或者在您的语言环境中形成有效字符的文件)。有些人也可以find
使用-r
, -R
,-d recurse
选项完成工作,尽管在处理非常规文件或在下降目录树时是否遵循目录的符号链接时,行为会有所不同。
通过 的busybox
实现grep
,您可以使用选项使其处理包含换行符的文本字符串-z
。-z
是使用以 NUL 分隔的记录而不是行,但根据定义,文本文件不能包含 NUL,无论如何您不能将 NUL 作为参数传递给命令或(除了 in zsh
)将它们存储在 shell 变量中,例如$string
.
所以:
string='1
2
3'
busybox grep -raFlze "$string" .
适用于任何输入的任意字符串。但是请注意busybox grep -r
(至少当前版本),查看任何类型的文件,包括符号链接、设备......所以你可能想要使用它find
而不是它-r
来限制到常规文件:
find . -type f -exec grep -aFlze "$string" {} +
(某些find
实现还可以在符号链接解析后-xtype f
检查文件类型,以在符号链接内搜索到常规文件)。
如果输入文件不包含 NUL 字节,则意味着每个文件最终都会被整个加载到内存中,因此它不能很好地扩展到非常大的文件。
对于可能包含 NUL 的任意数据和任何大小的文件,您可以存储字符串以在文件中搜索并用于mmap()
避免加载内存中已满的文件。有了perl
你可以这样做:
needle_file=needle.bin # containing the string to search
size=$(wc -c < "$needle_file")
find . -type f -size "+$(( size - 1 ))c" -exec perl -MSys::Mmap -le '
$needle = shift;
open NEEDLE, "<", $needle or die "$needle: $!\n";
mmap($needle, 0, PROT_READ, MAP_SHARED, NEEDLE);
for (@ARGV) {
if (open HAYSTACK, "<", $_) {
mmap($haystack, 0, PROT_READ, MAP_SHARED, HAYSTACK);
print if index($haystack, $needle) >= 0
} else {
warn "$_: $!\n"
}
}' -- "$needle_file" {} +
(请注意,Sys::Mmap
它不是perl
的核心模块之一,您可能必须像从libsys-mmap-perl
Debian 上的软件包一样安装它)。
我不知道perl
的index()
子字符串搜索算法在查找子字符串方面的效率如何。
zsh
可以将 NUL 存储在其变量中,并且可以将文件的内容映射到变量,因此您可以执行以下操作:
zmodload zsh/mapfile
set +o multibyte
string=$'foo\nbar\0baz'
print -rC1 -- **/*(ND.L+$(($#string - 1))e['[[ $mapfile[$REPLY] = *$string* ]]'])
但请注意,虽然zsh
确实mmap()
在下面使用,但它最终也会将文件内容复制到内存中,而且它是一个 shell,我怀疑它是否已被优化到与perl
.
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句