Get line number from preg_match_all()

前端 未结 10 954
天命终不由人
天命终不由人 2021-02-07 09:23

I\'m using PHP\'s preg_match_all() to search a string imported using file_get_contents(). The regex returns matches but I would like to know at which line number those matches a

10条回答
  •  庸人自扰
    2021-02-07 09:55

    This works but performs a new preg_match_all on every line which could be quite expensive.

    $file = file.txt;
    
    $log = array();
    
    $line = 0;
    
    $pattern = '/\x20{2,}/';
    
    if(is_readable($file)){
    
        $handle = fopen($file, 'rb');
    
        if ($handle) {
    
            while (($subject = fgets($handle)) !== false) {
    
                $line++;
    
                if(preg_match_all ( $pattern,  $subject, $matches)){
    
                    $log[] = array(
                        'str' => $subject, 
                        'file' =>  realpath($file),
                        'line' => $line,
                        'matches' => $matches,
                    );
                } 
            }
            if (!feof($handle)) {
                echo "Error: unexpected fgets() fail\n";
            }
            fclose($handle);
        }
    }
    

    Alternatively you could read the file once yo get the line numbers and then perform the preg_match_all on the entire file and catpure the match offsets.

    $file = 'file.txt';
    $length = 0;
    $pattern = '/\x20{2,}/';
    $lines = array(0);
    
    if(is_readable($file)){
    
        $handle = fopen($file, 'rb');
    
        if ($handle) {
    
            $subject = "";
    
            while (($line = fgets($handle)) !== false) {
    
                $subject .= $line;
                $lines[] = strlen($subject);
            }
            if (!feof($handle)) {
                echo "Error: unexpected fgets() fail\n";
            }
            fclose($handle);
    
            if($subject && preg_match_all ( $pattern, $subject, $matches, PREG_OFFSET_CAPTURE)){
    
                reset($lines);
    
                foreach ($matches[0] as $key => $value) {
    
                    while( list($line, $length) = each($lines)){ // continues where we left off
    
                        if($value[1] < $length){
    
                            echo "match is on line: " . $line;
    
                            break; //break out of while loop;
                        }
                    }
                }
            }
        }
    }}
    

提交回复
热议问题