2016-12-05 6 views
2

Ich fand einen Code mit function ShellFolder($source, $search1, $search2){$shellBefehl... mit egrep. Funktioniert soweit ganz gut. Aber jetzt habe ich ein Problem, da die gesuchten Textdateien oft die gleichen Begriffe enthalten. Jetzt möchte ich zwei Suchbegriffe miteinander verknüpfen, die in einer Textdatei gefunden werden müssen. Das ist mein Code:PHP-Funktion ShellFolder und eine UND-Verknüpfung

<?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); 
} 

Könnte jemand helfen?

Antwort

1

Grep

Es ist möglich, mehrere Muster zu Grep über -E Option passieren, zum Beispiel. Aber Grep wird nach beliebigen der Muster suchen.

Wenn Sie die Suchmuster mit einem logischen UND verknüpfen möchten, ist Grep nicht geeignet, da es logisches UND nicht unterstützt. Es ist möglich, zu simulieren und zu mit einem Muster wie pattern1.*pattern2, wenn pattern1 soll pattern2 vorangehen:

$patterns = ['pattern1', 'pattern2']; 
$dir = escapeshellarg($dir); 
$pattern = escapeshellarg(implode('.*', $patterns)); 
$command = "egrep -o -w -l -a -r $pattern $dir"; 
exec($command, $output, $exit_status); 

Oder pattern1.*pattern2|pattern2.*pattern1 für jede Bestellung. Aber für den allgemeinen Fall ist das Muster suboptimal. Mit anderen Worten, Grep ist für den allgemeinen Fall nicht geeignet, und Sie sollten ein anderes Werkzeug verwenden.

AWK

Es gibt eine portable way to search for multiple patterns using AWK: awk '/pattern1/ && /pattern2/ && ... ' file. Allerdings akzeptiert AWK eine einzelne Datei, und Sie werden das Verzeichnis manuell zu durchlaufen haben und den Befehl für jede Datei anwenden:

<?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)); 
}); 

Beispielausgabe

File: ./file1 
Lines: 
123 sdfsf 456 
456 & 123 
-------- 
File: ./test/file1 
Lines: 
456123 

PHP

Das Beispiel oben kann einfach in eine reine PHP-Lösung umgewandelt werden (ohne die Shell-Befehle aufzurufen). Sie können die Datei Zeile für Zeile und Test lesen, wenn die Linie, die die Muster übereinstimmt preg_match() nach der Logik Ihrer Anwendung:

$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

Vielen Dank. Ich arbeite einfach. –

+0

@UweJansen, bitte akzeptieren Sie die Antwort, wenn es das Problem löst –