Grepの
これは、例えば、-E
オプションを介しGrepのに複数のパターンを通過することが可能です。しかし、Grepはのいずれかのパターンをで検索します。
検索パターンを論理ANDで結合する場合は、論理ANDをサポートしていないため、Grepは便利ではありません。 pattern1
がpattern2
に先行することになっている場合は、AND pattern1.*pattern2
ようなパターンでシミュレートすることが可能である:
$patterns = ['pattern1', 'pattern2'];
$dir = escapeshellarg($dir);
$pattern = escapeshellarg(implode('.*', $patterns));
$command = "egrep -o -w -l -a -r $pattern $dir";
exec($command, $output, $exit_status);
それともpattern1.*pattern2|pattern2.*pattern1
任意の順序のために。しかし、一般的な場合、パターンは最適ではない。言い換えると、Grepは一般的なケースには適していないため、別のツールを使用する必要があります。
AWK
portable way to search for multiple patterns using AWKがあります:awk '/pattern1/ && /pattern2/ && ... ' file
。しかし、AWKは、単一のファイルを受け取り、手動でディレクトリを反復処理し、各ファイルにコマンドを適用する必要があります:
<?php
/**
* Searches for lines matching all regexp patterns.
*
* @param string $dir Path to directory with text files
* @param array $patterns AWK patterns without regexp markers ('/')
* @return array Files matching all patterns
* @throws InvalidArgumentException
*/
function grepDir($dir, array $patterns, callable $callback) {
if (!$patterns) {
throw new InvalidArgumentException("Invalid patterns");
}
// Build command as awk '/pattern1/ && /pattern2/ && ... path-to-file'
$awk_script = '/' . implode('/ && /', $patterns) . '/';
$awk_script = escapeshellarg($awk_script);
$command_format = "awk $awk_script %s";
try {
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
$it->rewind();
while ($it->valid()) {
if (!$it->isDot()) {
$file_path = $it->key();
$command = sprintf($command_format, $file_path);
$output = null;
exec($command, $output, $exit_status);
if ($exit_status) {
trigger_error("Command failed: $command");
continue;
}
if ($output) {
$callback($file_path, $output);
}
}
$it->next();
}
} catch (Exception $e) {
trigger_error($e->getMessage());
return false;
}
return true;
}
$dir = '.';
$patterns = [ '456', '123' ];
grepDir($dir, $patterns, function ($file_path, array $output) {
printf("File: %s\nLines:\n%s\n--------\n",
$file_path, implode(PHP_EOL, $output));
});
サンプル出力
File: ./file1
Lines:
123 sdfsf 456
456 & 123
--------
File: ./test/file1
Lines:
456123
PHP
例シェルコマンドを呼び出すことなく、簡単に純粋なPHPソリューションに変換することができます。ラインは、アプリケーションのロジックに従ってpreg_match()
を使用したパターンと一致した場合には、ラインと試験によるファイルの行を読むことができます:
$patterns = ['456', '123'];
$file = 'file1'; // Replace with $it->key() in the example above
if (! $fp = fopen('file1', 'r')) {
throw new RuntimeException("Failed to open file $file");
}
while ($line = fgets($fp)) {
$matches = true;
foreach ($patterns as $pattern) {
// You might want to quote the pattern, if it isn't supposed to be
// interpreted as a regular expression:
// $pattern = preg_quote($pattern, '/');
if (!preg_match("/{$pattern}/", $line)) {
$matches = false;
break;
}
}
if ($matches) {
echo "Line $line matches all patterns\n";
}
}
fclose($fp);
多くの感謝を。私はうまくいきます。 –
@UweJansen、問題が解決する場合は、答えを受け入れてください –