襶:
首先,您的原始 PHP 语句:
$itemFullName = preg_replace("@^\b(([a-zA-Z]{1,3})?[0-9]{1,2}(\.|\-|X)[0-9]{1,2}(\s|\.|\-)?(X|x)?\s?[0-9]{1,3}\.?(([0-9]{1,3})?(X[0-9]{1,3})|(\s[0-9]\/[0-9]|\/[0-9]{1,3}))?(\s\#[0-9]{1,3}\/[0-9]{1,3})?)\s@", ' ', $itemFullName, -1, $sum);
如果您以自由间距模式编写它并带有如下注释,则会更具可读性(和可维护性):
整齐的:
$itemFullName = preg_replace("/(?#!php re_item_tidy Rev:20180207_0700)
^ # Anchor to start of string.
\b # String must begin with a word char.
( # $1: Unnecessary group.
([a-zA-Z]{1,3})? # $2: Optional 1-3 alphas.
[0-9]{1,2} # 1-2 decimal digits.
(\.|\-|X) # $3: Either a dot, hyphen or X.
[0-9]{1,2} # One or two decimal digits.
(\s|\.|\-)? # $4: Optional whitespace, dot or hyphen.
(X|x)? # $5: Optional X or x.
\s?[0-9]{1,3}\.? # Optional whitespace, 1-3 digits, optional dot.
( # $6: Optional ??? from 2 alternatives.
([0-9]{1,3})? # Either a1of2 $7: Optional 1-3 digits.
(X[0-9]{1,3}) # $8: X and 1-3 digits.
| ( # Or a2of2 $9: one ??? from 2 alternatives.
\s[0-9]\/[0-9] # Either a1of2.
| \/[0-9]{1,3} # Or a2of2.
) # End $9: one ??? from 2 alternatives.
)? # End $6: optional ??? from 2 alternatives.
( # $10: Optional sequence.
\s\#[0-9]{1,3} # whitespace, hash, 1-3 digits.
\/[0-9]{1,3} # Forward slash, 1-3 digits.
)? # End $10: Optional sequence
) # End $1: Unnecessary group.
\s # End with a single whitespace char.
/x", ' ', $itemFullName, -1, $sum);
批判:
这个正则表达式在性能方面确实不错。它在开头有一个字符串锚点的开头,这有助于它在不匹配的字符串中快速失败。它也没有任何回溯问题。但是,可以进行一些小的改进:
- 有三组备选方案,其中每个备选方案仅由一个字符组成——每一个都可以用一个简单的字符类替换。
- 有 10 个捕获组,但 preg_replace 不使用任何捕获的数据。这些捕获组可以更改为非捕获。
- 有几个不必要的组可以简单地删除。
- 第 2 组:
([a-zA-Z]{1,3})?
可以更简单地写为:[a-zA-Z]{0,3}
. 第 7 组有类似的结构。
- 开头的
\b
单词边界是不必要的。
- 使用 PHP,最好将正则表达式模式包含在单引号字符串中。双引号字符串有许多必须转义的元字符。单引号字符串只有两个:单引号和反斜杠。
- 有一些不必要的转义正斜杠。
另请注意,您正在使用该$sum
变量来计算preg_replace()
. 由于您^
在模式的开头有一个字符串锚点的开头,因此您只会有一个替换,因为您没有指定'm'
多行修饰符。我假设您实际上确实想要执行多个替换(并将它们计入$sum
),所以我添加了'm'
修饰符。
这是包含这些更改的改进版本:
整理:
$itemFullName = preg_replace('%(?#!php/m re_item_tidier Rev:20180207_0700)
^ # Anchor to start of string.
[a-zA-Z]{0,3} # Optional 1-3 alphas.
[0-9]{1,2} # 1-2 decimal digits.
[.X-] # Either a dot, hyphen or X.
[0-9]{1,2} # One or two decimal digits.
[\s.-]? # Optional whitespace, dot or hyphen.
[Xx]? # Optional X or x.
\s?[0-9]{1,3}\.? # Optional whitespace, 1-3 digits, optional dot.
(?: # Optional ??? from 2 alternatives.
[0-9]{0,3} # Either a1of2: Optional 1-3 digits
X[0-9]{1,3} # followed by X and 1-3 digits.
| (?: # Or a2of2: One ??? from 2 alternatives.
\s[0-9]/[0-9] # Either a1of2.
| /[0-9]{1,3} # Or a2of2.
) # End one ??? from 2 alternatives.
)? # End optional ??? from 2 alternatives.
(?: # Optional sequence.
\s\#[0-9]{1,3} # whitespace, hash, 1-3 digits.
/[0-9]{1,3} # Forward slash, 1-3 digits.
)? # End optional sequence
\s # End with a single whitespace char.
%xm', ' ', $itemFullName, -1, $sum);
但是请注意,如果有任何性能改进,我认为您不会看到太多 - 您的原始正则表达式非常好。您的性能问题可能来自程序的其他方面。
希望这可以帮助。
编辑 2018-02-07:删除无关的双引号,添加正则表达式 shebangs。