preg_match_all 在动态标签之间
preg_match_all between dynamic tags
我想获取我的每个虚拟主机配置并使用 preg_match_all 将它们放入一个数组中,这样我就可以从每个虚拟主机配置中提取信息,例如...
$vHostConfig = ' <VirtualHost *:80>
ServerName localhost
DocumentRoot c:/wamp/www
<Directory "c:/wamp/www/">
Options +Indexes +Includes +FollowSymLinks +MultiViews
AllowOverride All
Require local
</Directory>
</VirtualHost>
<VirtualHost *:8080>
ServerName testing.com
DocumentRoot c:/wamp/www/testing.com
<Directory "c:/wamp/www/testing.com">
Options +Indexes +Includes +FollowSymLinks +MultiViews
AllowOverride All
Require local
</Directory>
</VirtualHost>
<VirtualHost 127.0.0.1:80>
ServerName testing2.com
DocumentRoot c:/wamp/www/testing2.com
<Directory "c:/wamp/www/testing2.com">
Options +Indexes +Includes +FollowSymLinks +MultiViews
AllowOverride All
Require local
</Directory>
</VirtualHost>
# <VirtualHost *:80>
# ServerName testing3.com
# DocumentRoot c:/wamp/www/testing3.com
# <Directory "c:/wamp/www/testing3.com">
# Options +Indexes +Includes +FollowSymLinks +MultiViews
# AllowOverride All
# Require local
# </Directory>
# </VirtualHost>';
preg_match_all(<<what to put here>>, $vHostConfig, $vHostConfigMatches);
我只想获取行首没有# 的活动配置,这意味着我应该在 $vHostConfigMatches 数组中有三个以 <VirtualHost
开头并以 </VirtualHost>
结尾的字符串。这可能吗?
您可以按行拆分它:
$lines = explode(PHP_EOL, $vhostConfig);
过滤掉所有注释行:
$lines = array_filter($lines, function ($ele) { return substring($ele, 0) != "#"; });
把它放回去:
$vhostConfig = implode(PHP_EOL, $lines);
然后使用正则表达式拉取每个虚拟主机(您可能想要更精确的东西:
preg_match_all("@<VirtualHost [\d\.\*:]+>(.*?)</VirtualHost>@", $vhostConfig, $vhostConfigMatches);
未经测试,但应该给你想法。这也有忽略有效虚拟主机中任何注释行的好处
您可以使用这个正则表达式:
preg_match_all('/^\h*<VirtualHost.*?>.*?\R\h*<\/VirtualHost>/sm',
$vHostConfig, $vHostConfigMatches);
请注意数组 $vHostConfigMatches
将有一个额外的嵌套级别,因此只需使用第一个嵌套 reset
:
print_r(reset($vHostConfigMatches));
虽然@trincot 的答案工作正常,但它使用了 .*?
(惰性)量词,这使得正则表达式引擎非常活跃:这个 regex101 表明它在这个例子中需要 950 步。
所以我认为,即使看起来有点复杂,这个简单的 PHP 片段也会 运行 更快:
$result = array_reduce(
explode(PHP_EOL, $str),
function($result, $line) {
if (trim($line[0]) <> '#') {
if (strpos($line, '<VirtualHost') !== false) {
$result[] = $line;
} else {
$result[count($result) - 1] .= $line;
}
}
return $result;
},
[]
);
一下子,它只是:
- 将原始字符串转换为行数组
- 删除任何评论
- 按预期填充所需的结果
我想获取我的每个虚拟主机配置并使用 preg_match_all 将它们放入一个数组中,这样我就可以从每个虚拟主机配置中提取信息,例如...
$vHostConfig = ' <VirtualHost *:80>
ServerName localhost
DocumentRoot c:/wamp/www
<Directory "c:/wamp/www/">
Options +Indexes +Includes +FollowSymLinks +MultiViews
AllowOverride All
Require local
</Directory>
</VirtualHost>
<VirtualHost *:8080>
ServerName testing.com
DocumentRoot c:/wamp/www/testing.com
<Directory "c:/wamp/www/testing.com">
Options +Indexes +Includes +FollowSymLinks +MultiViews
AllowOverride All
Require local
</Directory>
</VirtualHost>
<VirtualHost 127.0.0.1:80>
ServerName testing2.com
DocumentRoot c:/wamp/www/testing2.com
<Directory "c:/wamp/www/testing2.com">
Options +Indexes +Includes +FollowSymLinks +MultiViews
AllowOverride All
Require local
</Directory>
</VirtualHost>
# <VirtualHost *:80>
# ServerName testing3.com
# DocumentRoot c:/wamp/www/testing3.com
# <Directory "c:/wamp/www/testing3.com">
# Options +Indexes +Includes +FollowSymLinks +MultiViews
# AllowOverride All
# Require local
# </Directory>
# </VirtualHost>';
preg_match_all(<<what to put here>>, $vHostConfig, $vHostConfigMatches);
我只想获取行首没有# 的活动配置,这意味着我应该在 $vHostConfigMatches 数组中有三个以 <VirtualHost
开头并以 </VirtualHost>
结尾的字符串。这可能吗?
您可以按行拆分它:
$lines = explode(PHP_EOL, $vhostConfig);
过滤掉所有注释行:
$lines = array_filter($lines, function ($ele) { return substring($ele, 0) != "#"; });
把它放回去:
$vhostConfig = implode(PHP_EOL, $lines);
然后使用正则表达式拉取每个虚拟主机(您可能想要更精确的东西:
preg_match_all("@<VirtualHost [\d\.\*:]+>(.*?)</VirtualHost>@", $vhostConfig, $vhostConfigMatches);
未经测试,但应该给你想法。这也有忽略有效虚拟主机中任何注释行的好处
您可以使用这个正则表达式:
preg_match_all('/^\h*<VirtualHost.*?>.*?\R\h*<\/VirtualHost>/sm',
$vHostConfig, $vHostConfigMatches);
请注意数组 $vHostConfigMatches
将有一个额外的嵌套级别,因此只需使用第一个嵌套 reset
:
print_r(reset($vHostConfigMatches));
虽然@trincot 的答案工作正常,但它使用了 .*?
(惰性)量词,这使得正则表达式引擎非常活跃:这个 regex101 表明它在这个例子中需要 950 步。
所以我认为,即使看起来有点复杂,这个简单的 PHP 片段也会 运行 更快:
$result = array_reduce(
explode(PHP_EOL, $str),
function($result, $line) {
if (trim($line[0]) <> '#') {
if (strpos($line, '<VirtualHost') !== false) {
$result[] = $line;
} else {
$result[count($result) - 1] .= $line;
}
}
return $result;
},
[]
);
一下子,它只是:
- 将原始字符串转换为行数组
- 删除任何评论
- 按预期填充所需的结果