Allan Thomas
Allan Thomas

Reputation: 3589

Regex to match specific values from from an Apache virtualhost file

I want to match the values defined as ServerName, ServerAlias and DocumentRoot with regex.

Anything with a preceding # can be ignored.

I also would like to keep each virtualhost's definitions separate so in the example below I'd have two arrays.

Example:

<VirtualHost *:80>
  ServerName foo.com
  ServerAlias stage.foo.com new.foo.com
  DocumentRoot /var/www/foo.com
</VirtualHost>

<VirtualHost *:80 *:443>
  ServerName bar.com
  ServerAlias store.bar.com
  #ServerAlias new.bar.com us.bar.com
  DocumentRoot /var/www/bar.com
</VirtualHost>

My work:

<VirtualHost(?: \*\:[0-9]*)+>\s* will match each virtual hosting opening "tag" plus trailing white space.

[^\#](?:ServerName|ServerAlias|DocumentRoot) ((?:(?:[\w\/\._-]+) ?)+) will match the values I need but not as separate virtualhosts/sets/arrays.

I'm having trouble connecting them together.

Upvotes: 2

Views: 1044

Answers (2)

Jin Chen
Jin Chen

Reputation: 642

Here is a perl version:

$in = 0;
while ($line = <>) {
  if ($line =~ m/<VirtualHost(?: \*\:[0-9]*)+>\s*/) {
    $in = 1;
  }
  if ($line =~ m/<\/VirtualHost>/) {
    $in = 0;
  }

  if ($in eq 1) {
    if (!($line =~ m/#/) && $line =~ m/(?:ServerName|ServerAlias|DocumentRoot) ((?:(?:[-\w\/.]+) ?)+)/) {
        print $1;
        print "\n";
    }
  }
}

Upvotes: 0

anubhava
anubhava

Reputation: 785266

It required more code than I initially thought. Consider this code:

$s = <<< EOF
<VirtualHost *:80>
  ServerName foo.com
  ServerAlias stage.foo.com new.foo.com
  DocumentRoot /var/www/foo.com
</VirtualHost>

<VirtualHost *:80 *:443>
  ServerName bar.com
  ServerAlias store.bar.com
  #ServerAlias new.bar.com us.bar.com
  DocumentRoot /var/www/bar.com
</VirtualHost>
EOF;
$vh = array();
if (preg_match_all('~<VirtualHost ([^>]+)>(.+?)</VirtualHost>~is', $s, $arr)) {
   for($i=0; $i < count($arr[1]); $i++) {
       if (preg_match_all('/^ *(ServerName|ServerAlias|DocumentRoot) +(.+)$/im', 
                               $arr[2][$i], $m)) {
          $entries = array();
          for($j=0; $j < count($m[1]); $j++)
             $entries[$m[1][$j]] = $m[2][$j];
          $vh[$arr[1][$i]] = $entries;
       }
   }
}
print_r($vh);

OUTPUT:

Array
(
    [*:80] => Array
        (
            [ServerName] => foo.com
            [ServerAlias] => stage.foo.com new.foo.com
            [DocumentRoot] => /var/www/foo.com
        )

    [*:80 *:443] => Array
        (
            [ServerName] => bar.com
            [ServerAlias] => store.bar.com
            [DocumentRoot] => /var/www/bar.com
        )
)

Upvotes: 3

Related Questions