Search code examples
phpregexpattern-matchingpreg-replacepreg-grep

Grep for a specific pattern in a file and stop at the first match


I have a bunch of Nginx vhost files like this:

# This file was autogenerated by Puppet [ wordpress::vhost ]
# Any manual edit to this file will be automatically removed
# ©2016, DevOps team

server {
    listen 443 ssl;

    root /var/www/as888;
    index index.php;

    server_name wptraining-sdemo.mysysweb.com;
    ......
    ......

and I need to extract the value of the server_name directive (i.e. wptraining-sdemo.mysysweb.com in this case) from each file. I tried this, using preg_replace:

$host_dir = '/etc/nginx/sites-enabled';
$_pattern = '/^.*server_name (.*);$/U';

$_clients = scandir($host_dir);
foreach ( $_clients as &$client ) {
    if ( preg_match('/^as[0-9]{3}$/', $client, $matchs) ) {
        $wp_domain = preg_replace($_pattern, "$1", file("{$host_dir}/{$matchs[0]}"));
        echo "{$matchs[0]} => {$wp_domain[0]}";
    }
}

and I get the very 1st line of the file in return:

as888 => # This file was autogenerated by Puppet [ wordpress::vhost ]

if I use preg_grep instead:

$wp_domain = preg_grep($_pattern, file("{$host_dir}/{$matchs[0]}"));
print_r($wp_domain);

I get something like this:

Array
(
    [10] =>     server_name wptraining-sdemo.mysysweb.com;

)

which is rather strange to me, as I was expecting [0] (as there gonna be only one match) instead of [10]. Looks like it's creating an array with each line in the file.

what I'm doing wrong? And most importantly, what am I missing? I'm not very familiar with PHP and kind of lost in this. None of the help/posts, available in the net, worked. Basically, something similar to this: sed -n -e 's|^.*server_name \(.*\);$|\1|p' <file_name>, I believe. Any help would be greatly appreciated. Best!


Solution

  • You may use

    preg_match('~server_name\h*(.*);~', $s, $match); 
    echo $match[1];
    

    See this regex demo

    Details

    • server_name - a literal substring
    • \h* - 0+ horizontal whitespaces
    • (.*) - Group 1: any 0+ chars other than line break chars
    • ; - a ;.

    Actually, I think your approach will work if you add m modifier:

    $_pattern = '/^.*server_name (.*);$/m';
    

    See this demo

    *Details**:

    • ^.* - start of a line and then any 0+ chars other than line break chars
    • server_name - a literal substring
    • - space
    • (.*) - Group 1: any 0+ chars other than line break chars
    • ; - a ;.
    • $ - end of a line