在为您的项目确定最佳模式时,您需要考虑以下模式因素:
- 准确性(稳健性)- 模式是否在所有情况下都是正确的,并且是否合理地面向未来
- 效率——模式应该是直接的、深思熟虑的,避免不必要的劳动
- 简洁——模式应该使用适当的技术来避免不必要的字符长度
- 可读性——模式应尽可能简单
以上因素也恰好是在努力服从的等级秩序中。换句话说,当 1 不能完全满足要求时,优先考虑 2、3 或 4 对我来说没有多大意义。对我来说,可读性位于列表的底部,因为在大多数情况下我可以遵循语法。
捕获组和 Lookarounds 通常会影响模式效率。事实是,除非您在数千个输入字符串上执行此正则表达式,否则无需为效率而努力。可能更重要的是关注与模式简洁相关的模式可读性。
下面的一些模式需要通过它们的preg_ 函数进行一些额外的处理/标记,但这里有一些基于 OP 示例输入的模式比较:
preg_split() 模式:
-
/^[^A-Z]+\K|[A-Z][^A-Z]+\K/(21 步)
-
/(^[^A-Z]+|[A-Z][^A-Z]+)/(26 步)
-
/[^A-Z]+\K(?=[A-Z])/(43 步)
-
/(?=[A-Z])/(50 步)
-
/(?=[A-Z]+)/(50 步)
-
/([a-z]{1})[A-Z]{1}/(53 步)
-
/([a-z0-9])([A-Z])/(68 步)
-
/(?<=[a-z])(?=[A-Z])/x(94 步)...作为记录,x 没用。
-
/(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/(134 步)
preg_match_all() 模式:
-
/[A-Z]?[a-z]+/(14 步)
-
/((?:^|[A-Z])[a-z]+)/(35 步)
我会指出preg_match_all() 和preg_split() 的输出之间存在细微差别。 preg_match_all() 将输出一个二维数组,换句话说,所有的全字符串匹配都将在[0] 子数组中;如果使用了捕获组,则这些子字符串将位于 [1] 子数组中。另一方面,preg_split() 只输出一个一维数组,因此提供了一个不那么臃肿且更直接的路径到所需的输出。
在处理其中包含全大写/首字母缩略词子字符串的驼峰式字符串时,某些模式是不够的。如果这是您项目中可能出现的边缘情况,则只考虑正确处理这些情况的模式是合乎逻辑的。我不会测试 TitleCase 输入字符串,因为这离问题太远了。
新的扩展测试串电池:
oneTwoThreeFour
hasConsecutiveCAPS
newNASAModule
USAIsGreatAgain
合适的preg_split()模式:
-
/[a-z]+\K|(?=[A-Z][a-z]+)/(149 步)*我必须使用 [a-z] 才能让演示正确计数
-
/(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/(547 步)
适合preg_match_all()模式:
-
/[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|$)/(75 步)
最后,我的建议基于我的模式原则/因素层次结构。此外,我推荐preg_split() 而不是preg_match_all()(尽管模式的步骤更少)作为对所需输出结构的直接性问题。 (当然,选择你喜欢的)
代码:(Demo)
$noAcronyms = 'oneTwoThreeFour';
var_export(preg_split('~^[^A-Z]+\K|[A-Z][^A-Z]+\K~', $noAcronyms, 0, PREG_SPLIT_NO_EMPTY));
echo "\n---\n";
var_export(preg_match_all('~[A-Z]?[^A-Z]+~', $noAcronyms, $out) ? $out[0] : []);
代码:(Demo)
$withAcronyms = 'newNASAModule';
var_export(preg_split('~[^A-Z]+\K|(?=[A-Z][^A-Z]+)~', $withAcronyms, 0, PREG_SPLIT_NO_EMPTY));
echo "\n---\n";
var_export(preg_match_all('~[A-Z]?[^A-Z]+|[A-Z]+(?=[A-Z][^A-Z]|$)~', $withAcronyms, $out) ? $out[0] : []);