在多个文件中搜索字符串,而不使用正则表达式?

在多个文件中搜索字符串,而不使用正则表达式?

是否有一个命令可以在多个文件中搜索一个字符串,但该命令(可能由某个选项修改)不支持正则表达式?我希望这样可以避免使用正则表达式,而且不必转义特殊字符。

(如果知道在目录及其子目录中递归搜索的选项也很好。)

答案1

如果文件是文本文件并且字符串不包含换行符,则可以grep-F(forfixed-string) 选项一起使用。

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 传递给命令或(除了在 中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-perlDebian 上的软件包一样安装它)。

我无法判断 的子字符串搜索算法查找子字符串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.

答案2

关于什么:

grep -inH -r "search_string" *

相关内容