Get line number from preg_match_all()

前端 未结 10 948
天命终不由人
天命终不由人 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
    //Keep it simple, stupid
    
    $allcodeline = explode(PHP_EOL, $content);
    
    foreach ( $allcodeline as $line => $val ) :
        if ( preg_match("#SOMEREGEX#i",$val,$res) ) {
            echo $res[0] . '!' . $line . "\n";
        }
    endforeach;
    
    0 讨论(0)
  • 2021-02-07 09:59

    Late to the game but I needed this functionality today and I realized that @Javier's and @iguito's answers could be combined into a simple solution. I also replaced the check for \n with PHP_EOL for my use case:

    // Get your matches
    preg_match_all( '[YOUR REGEX HERE]', $data, $matches, PREG_OFFSET_CAPTURE );
    
    // This is my loop format, yours may need to be different
    foreach ( $matches[0] as $match ) {
    
        // Get the line number for the current match 
        list( $before ) = str_split( $data, $match[1] );
        $line_number = substr_count( $before, PHP_EOL ) + 1;
        echo $line_number;
    
    }
    
    0 讨论(0)
  • 2021-02-07 10:05
    $data = "Abba
    Beegees
    Beatles";
    
    preg_match_all('/Abba|Beegees|Beatles/', $data, $matches, PREG_OFFSET_CAPTURE);
    foreach (current($matches) as $match) {
        $matchValue = $match[0];
        $lineNumber = substr_count(mb_substr($data, 0, $match[1]), PHP_EOL) + 1;
    
        echo "`{$matchValue}` at line {$lineNumber}\n";
    }
    

    Output

    `Abba` at line 1
    `Beegees` at line 2
    `Beatles` at line 3
    

    (check your performance requirements)

    0 讨论(0)
  • 2021-02-07 10:07

    You have got a couple options, but none are "simple":

    a) exec() and use the system grep command, which can report line numbers:

    exec("grep -n 'your pattern here' file.txt", $output);`
    

    b) Slurp in the file using file_get_contents(), split it into an array of lines, then use preg_grep() to find the matching lines.

    $dat = file_get_contents('file.txt');
    $lines = explode($dat, "\n");
    $matches = preg_grep('/your pattern here/', $lines);
    

    c) Read the file in line-sized chunks, keep a running line count, and do your pattern match on each line.

    $fh = fopen('file.txt', 'rb');
    $line = 1;
    while ($line = fgets($fh)) {
         if (preg_match('/your pattern here/', $line)) {
             ... whatever you need to do with matching lines ...
         }
         $line++;
    }
    

    Each has its ups and downs

    a) You're invoking an external program, and if your pattern contains any user-supplied data, you're potentially opening yourself up to the shell equivalent of an SQL injection attack. On the plus side, you don't have to slurp in the entire file and will save a bit on memory overhead.

    b) You're safe from shell injection attacks, but you have to slurp in the entire file. If your file is large, you'll probably exhaust available memory.

    c) You're invoking a regex every line, which would have significant overhead if you're dealing with a large number of lines.

    0 讨论(0)
提交回复
热议问题