2016-12-05 56 views
2

我找到一个代码function ShellFolder($source, $search1, $search2){$shellBefehl...egrep。迄今为止工作得很好。但是现在我遇到了问题,因为搜索到的文本文件通常包含相同的术语。现在我想链接两个搜索词,它们必须在文本文件中找到。这是我的代码:php函数ShellFolder和一个AND链接

<?php 
function ShellFolder($source, $search1, $search2){ 
    $shellBefehl = "egrep -o -w -l -a --directories=recurse '$search1' '$search2' $source"; 
    exec($shellBefehl, $var); 
    return $var; 
} 

//$source = 'grep.txt'; 
$source = './ordner/daten'; 
$search1 = $this->item->title; 
$search2 = $extraField->value; 
$var = ShellFolder($source, $search1, $search2); 

$myResult = print_r($var, true); 

$text = $myResult; 
$text_ohne = substr($myResult, 19); 
$insgesamt = $text_ohne; 
$insgesamt_neu=substr($insgesamt,0,-3); 
echo ($search1); 
echo ($search2); 
$lines = file("$insgesamt_neu"); 

foreach($lines as $line) { 
    echo($line); 
} 

任何人都可以帮忙吗?

回答

1

的grep

有可能经由-E选项以多个图案传递给grep的,例如。但Grep会搜索的任何的模式。

如果您想要使用逻辑AND连接搜索模式,那么Grep并不方便,因为它不支持逻辑AND。它可以模拟,并与像pattern1.*pattern2一个模式,如果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 AWKawk '/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解决方案(不需要调用shell命令)。您可以逐行读取文件,并根据您的应用逻辑测试行是否匹配使用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); 
+0

非常感谢。我只是工作。 –

+0

@UweJansen,如果解决了问题,请接受答案 –