Dave
Dave

Reputation: 43

PHP Regex nongreedy match doesn't work correctly on some servers

I have the following minimal example that behaves differently on a local server (WAMP, PHP 7.3.7) and on a production server with PHP 7.3.27. The result on the local server seems wrong to me because the lazy modifier is ignored. The result is also in conflict with all the regex testers I have tried.

Example code:

<?php
header('Content-Type: text/plain; charset=utf-8');

$input = <<<EOT
John Smith
John Smith (123)
John Smith (123) (456)
EOT;


preg_match_all('/(.+?)(?:\s\((\d+)\))?$/m', $input, $matches_defines);
print_r($matches_defines);

?>

Result in local environment:

Array
(
    [0] => Array
        (
            [0] => John Smith
            [1] => John Smith (123)
            [2] => John Smith (123) (456)
        )

    [1] => Array
        (
            [0] => John Smith
            [1] => John Smith (123)
            [2] => John Smith (123)
        )

    [2] => Array
        (
            [0] => 
            [1] => 
            [2] => 456
        )
)

Result in production environments:

Array
(
    [0] => Array
        (
            [0] => John Smith
            [1] => John Smith (123)
            [2] => John Smith (123) (456)
        )

    [1] => Array
        (
            [0] => John Smith
            [1] => John Smith
            [2] => John Smith (123)
        )

    [2] => Array
        (
            [0] => 
            [1] => 123
            [2] => 456
        )
)

Can somebody tell me where this difference comes from and what adjustments can be made in the local environment to correct it?

Upvotes: 1

Views: 47

Answers (1)

Dave
Dave

Reputation: 43

Okay, answering my own question here: This is a Windows/Linux line ending issue.

The regex on my local server fails because in the text, there is a \r after every closing bracket. So the closing bracket is not the end of a line, there is an additional character, \r before the end of the line ($). (Source)

This can be fixed with a slightly modified regex: /(.+?)(?:\s\((\d+)\))?\s*$/m. Note the \s* at the end. This matches the \r at the end of the line if it's there.

Upvotes: 0

Related Questions