这个问题有点奇怪,我花了一些时间来推动我对正则表达式的了解,以达到它的目的。然而,我却陷入了最后一点。问题如下:
我有一个字符串(表示我正在修改的路由系统中的url),可能包含一个匹配某个段的正则表达式。例如:
$pattern = "/some/path/to/</[a-z]+/>regex_var1/location";
这里要注意的重点是:
</
/>
分隔(除非由于遗留原因而导致世界末日,否则这不是特别可选的。我宁愿保留原样)。< / LI>
/>
(regex_var1)之后的文本位是此参数匹配的名称。我需要将其保留在表达式之外,以使其与系统的其余部分兼容,足以说在此上下文中可以忽略它。/some/path/to/another/location
我想要实现的是将给定格式(如上所示)分割成段。这些段用于回溯树遍历以将请求URI与控制器匹配。目前不支持正则表达式,我的意图是允许这样做。在过去,每个细分都用/
表示,但是我在所包含的正则表达式中需要/
个字符。如果我在它的当前形式中使用它,则表达式分为两个段。例如
$pattern = "/some/</([a-z]+)(/optional)?/>regex2/location";
$segments = preg_split('/(?<!<)\/(?!>)/', $pattern);
产生4个部分
// print_r($segments)
Array
(
[0] =>
[1] => some
[2] => </([a-z]+)(
[3] => optional)?/>regex2
[4] => location
)
当我实际上只想要3
时// print_r($segments)
Array
(
[0] =>
[1] => some
[2] => </([a-z]+)(/optional)?/>regex2
[3] => location
)
我对将整个网址与正则表达式匹配不感兴趣,这会破坏整个练习的重点。这个问题可能在单独的情况下看来是没有根据的,但是关于为什么我在此特定实现之后的详细信息超出了问题的范围。
答案 0 :(得分:2)
嗯,我看不到只用正则表达式来做这件事的简单方法。您可能首先解析出正则表达式(/<\/.*?\/>[^\/]*/
),将它们存储在一个数组中并用简单但不碰撞的东西($1
)替换它们,然后运行正则表达式并重新插入正则表达式。
答案 1 :(得分:0)
另一种方法:
$str = "/some/</([a-z]+)(/optional)?/>regex2/location";
$out_segments = array();
$in_regex = false;
foreach(preg_split('+/+', $str) as $segment) {
if ($in_regex) {
if (substr($segment, 0, 1) === '>') {
$in_regex = false;
}
$out_segments[count($out_segments) - 1] .= "/$segment";
continue;
}
if (!$in_regex && substr($segment, -1, 1) === '<') {
$segment = substr($segment, 0, -1);
if ($segment !== '') {
$out_segments[] = $segment;
}
$in_regex = true;
$segment = '<';
}
if ($segment !== '') {
$out_segments[] = $segment;
}
}
var_dump($out_segments);
编辑:错误的伪代码看起来更容易。不过,这个想法并不是那么糟糕。
答案 2 :(得分:0)
您可以先尝试将字符串拆分为其组件,然后再处理它:
$url = '/some/location/</([a-z]+)(/optional)?/>regex2/here/or/there';
$reg = '#(.*?)(</.*?/>.*?(?=/|$))(.*)?#';
if( preg_match($reg, $url, $matches) ) {
$result = array_merge(
preg_split( '#/#', $matches[1], 0, PREG_SPLIT_NO_EMPTY),
array( $matches[2] ),
preg_split( '#/#', $matches[3], 0, PREG_SPLIT_NO_EMPTY)
);
print_r( $result );
}
Array
(
[0] => some
[1] => location
[2] => </([a-z]+)(/optional)?/>regex2
[3] => here
[4] => or
[5] => there
)
正则表达式应始终位于$matches[2]
中,因此无论网址出现在何处,您都可以找到它。