正規表現を使用せずに複数のファイルから文字列を検索しますか?

正規表現を使用せずに複数のファイルから文字列を検索しますか?

複数のファイルから文字列を取得するためのコマンドがありますが、そのコマンド(おそらくオプションで修正)は正規表現をサポートしていませんか?これは正規表現の使用を避け、特殊文字をエスケープしないことを願っています。

(ディレクトリとサブディレクトリ内で再帰的に検索するオプションを知っておくとよいでしょう。)

ベストアンサー1

ファイルがテキストファイルで、文字列に改行文字が含まれていない場合(forfixed-string)オプション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 を含めることはできませんzsh$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コアモジュールの1つではありません。Debianのパッケージからインストールする必要があるperlかもしれません。)libsys-mmap-perl

部分文字列検索アルゴリズムが部分文字列を見つけるのにどれだけ効率的かはわかりませんperlindex()

zshNULはその変数に保存でき、ファイルの内容は変数にマップでき、次のことができます。

zmodload zsh/mapfile
set +o multibyte
string=$'foo\nbar\0baz'
print -rC1 -- **/*(ND.L+$(($#string - 1))e['[[ $mapfile[$REPLY] = *$string* ]]'])

しかし、zsh以下では動作しますが、mmap()最終的にはファイルの内容をメモリにコピーし、シェルなのでperl

おすすめ記事