複数行文字列のディレクトリ検索

複数行文字列のディレクトリ検索

複数行の文字列を含むリポジトリ内のすべてのファイルを再帰的に検索し、それを含むファイル名を返す方法を探しています。段落は約30行のタイトルにすぎません。そのため、pcregrep複数行検索が可能であることを知っています。しかし、完全な表現を入れなければなりません。これは私が探している長い段落なので、変数に入れてからその変数をgrepしたいと思います。だから基本的にそれはすべてです。find . -name "*.[ch]" | xargs pcregrep -M $paragraphしかし、これはうまくいきません。誰もが正しい方向に私を指すことができますか?

答え1

ファイルの最初の30行を一致させようとしているので、テキストをファイルに保存し、それを使用して参照ref_fileファイルをdiff各ファイルの最初の30行と比較することができます。

find . -name "*.[ch]" -exec ./myscript {} \; -print

./myscriptどこ

#!/bin/sh

head -n 30 "$1" | diff - /path/to/ref_file >/dev/null

したがって、-print最初のコマンド-execは、前のコマンドが評価された場合にのみ実行されます。本物つまり、参照ファイルの最初の30行と現在のファイルの間に違いはありません。
または、スクリプトを使用せずにファイル名を次の場所に保存する場合logfile

find . -type f -exec sh -c 'head -n 30 "$0" | diff - /path/to/ref_file >/dev/null' {} \; -print >logfile

これは正確に一致するものを探していると仮定します。それ以外の場合、違いが1つの空白であってもdiff終了します。1

答え2

処理したい各ファイルを見つけてfind一致を見つけて一致する場合は、ファイル名を印刷する特別に生成されたスクリプトに各ファイル名を指定できるため、1行のスクリプトではなくスクリプトを使用することをお勧めします。プロンプト複数行文字列を簡単に処理できます。

それは:

find . -name "*.[ch]" -exec /path/to/script {} \;

scriptこのPerlスクリプトはどこにありますか?

#! /usr/bin/perl

$/ = ""; # sets the input record separator to an empty string
$_ = <>; # stores the content of the file specified in the first argument in $_

$string = <<EOF; # The multi-line string to match starts here
My
multiline
string
EOF
# The multi-line string to match ends here

/\Q$string\E/ && print($ARGV."\n"); # If $_ matches $string, prints the name of the file
  • $/ = "";:Perlの入力レコード区切り文字を空の文字列に設定します。これは、Perlがスクリプトの最初の引数で指定されたファイル全体をすぐに読み取ることを可能にします。
  • $_ = <>;:の最初のパラメータで指定されたファイルの内容を保存します$_
  • $string = <<EOF;[...] EOF:[...]の内容を保存します$string([...]を一致させる複数行の文字列に置き換えます)。
  • /\Q$string\E/ && print($ARGV."\n");$_一致するものがあれば$stringファイル名を印刷します。

以下は、特別に作成されたテストディレクトリ階層のサンプル出力です。

% for f in *; do printf '%s:\n\n' "$f"; <<<'' cat "$f" -; done
file1:

My
multiline
string

file2:

My
multiline
string

file3:

My
other
multiline
string

script.pl:

#! /usr/bin/perl

$/ = "";
$_ = <>;

$string = <<EOF;
My
multiline
string
EOF

$string = quotemeta($string);

/$string/&&print($ARGV."\n");

% find . -type f -exec ./script.pl {} \;                      
./file2
./file1

関連情報