分裂的魔力。我最初的假设在技术上是不正确的(尽管更容易找到一个解决方案)。因此,让我们检查您的拆分模式:
(\/|\.|-|_|=|\?|\&|html|shtml|www|php|cgi|htm|aspx|asp|index|com|net|org|%|\+)
我稍微重新安排了一下。不需要外括号,我将单个字符移到最后的字符类中:
html|shtml|www|php|cgi|htm|aspx|asp|index|com|net|org|[\/._=?&%+-]
这对于一些预先排序。让我们将这种模式称为拆分模式,s
简而言之并对其进行定义。
您希望匹配不属于 split-at 模式中的那些字符的所有部分,并且至少匹配三个字符。
我可以通过以下模式实现这一点,包括支持正确的拆分序列和 unicode 支持。
$pattern = '/
(?(DEFINE)
(?<s> # define subpattern which is the split pattern
html|shtml|www|php|cgi|htm|aspx|asp|index|com|net|org|
[\\/._=?&%+-] # a little bit optimized with a character class
)
)
(?:(?&s)) # consume the subpattern (URL starts with \/)
\K # capture starts here
(?:(?!(?&s)).){3,} # ensure this is not the skip pattern, take 3 characters minimum
/ux';
或者更小:
$path = '/2009/06/pagerank-update.htmltesthtmltest%C3%A4shtml';
$subject = urldecode($path);
$pattern = '/(?(DEFINE)(?<s>html|shtml|www|php|cgi|htm|aspx|asp|index|com|net|org|[\\/._=?&%+-]))(?:(?&s))\K(?:(?!(?&s)).){3,}/u';
$word_array = preg_match_all($pattern, $subject, $m) ? $m[0] : [];
print_r($word_array);
结果:
Array
(
[0] => 2009
[1] => pagerank
[2] => update
[3] => test
[4] => testä
)
也可以使用相同的原理preg_split
。有点不同:
$pattern = '/
(?(DEFINE) # define subpattern which is the split pattern
(?<s>
html|shtml|www|php|cgi|htm|aspx|asp|index|com|net|org|
[\/._=?&%+-]
)
)
(?:(?!(?&s)).){3,}(*SKIP)(*FAIL) # three or more is okay
|(?:(?!(?&s)).){1,2}(*SKIP)(*ACCEPT) # two or one is none
|(?&s) # split @ split, at least
/ux';
用法:
$word_array = preg_split($pattern, $subject, 0, PREG_SPLIT_NO_EMPTY);
结果:
Array
(
[0] => 2009
[1] => pagerank
[2] => update
[3] => test
[4] => testä
)
这些例程按要求工作。但这确实有其价格和性能。成本与旧答案相似。
相关问题:
旧答案,进行两步处理(先拆分,然后过滤)
因为您使用的是拆分例程,所以无论长度如何,它都会拆分。
所以你可以做的是过滤结果。您可以使用正则表达式 ( preg_filter
) 再次执行此操作,例如删除所有较小的三个字符的表达式:
$word_array = preg_filter(
'/^.{3,}$/', '$0',
preg_split(
'/(\/|\.|-|_|=|\?|\&|html|shtml|www|php|cgi|htm|aspx|asp|index|com|net|org|%|\+)/',
urldecode($path),
NULL,
PREG_SPLIT_NO_EMPTY
)
);
结果:
Array
(
[0] => 2009
[2] => pagerank
[3] => update
)