gpt4 book ai didi

PHP 正则表达式性能

转载 作者:可可西里 更新时间:2023-10-31 23:51:45 26 4
gpt4 key购买 nike

我必须从字符串中取出一些数据。不幸的是,数据的格式非常不友好。我必须创建大约 15 个正则表达式放在单独的 preg_replace 中。值得一提的是,它们本身就有很多或(|)。我的问题是我最终应该做什么:将所有表达式合并为一个并使用 | 将它们分开或者让它们保持原样 - 在单独的 preg_replace 中?

创建其他表达式以保持清晰度是非常糟糕的做法吗?我想也许我可以将一些表达组合成一个,但它们变得非常复杂并且不理解。

例如我有:

$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);

最佳答案

不整洁:

对于初学者,您的原始 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);

批评:

这个正则表达式在性能方面确实不错。它在开始时有一个字符串 anchor 的开始,这有助于它针对不匹配的字符串快速失败。它也没有任何回溯问题。但是,可以进行一些小的改进:

  • 共有三组备选方案,其中每组备选方案仅包含一个字符 - 每一个都可以用一个简单的字符类替换。
  • 有 10 个捕获组,但 preg_replace 不使用任何捕获的数据。这些捕获组可以更改为非捕获。
  • 有几个不需要的组可以简单地删除。
  • 第 2 组:([a-zA-Z]{1,3})? 可以更简单地写为:[a-zA-Z]{0,3} 。第 7 组具有类似的结构。
  • 开头的\b字边界是不必要的。
  • 对于 PHP,最好将正则表达式模式包含在单引号字符串中。双引号字符串有许多必须转义的元字符。单引号字符串只有两个:单引号和反斜杠。
  • 有一些不必要的转义正斜杠。

另请注意,您正在使用 $sum 变量来计算 preg_replace() 进行的替换次数。由于您在模式的开头有一个 ^ 开始的字符串 anchor ,您将只有一个替换,因为您没有指定 '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:删除了多余的双引号,添加了正则表达式 shebang。

关于PHP 正则表达式性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18686168/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com