Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/248.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP正则表达式性能_Php_Regex_Preg Replace - Fatal编程技术网

PHP正则表达式性能

PHP正则表达式性能,php,regex,preg-replace,Php,Regex,Preg Replace,我必须从字符串中取出一些数据。不幸的是,数据的格式确实不友好。我必须创建大约15个正则表达式,放在单独的preg__替换中。值得一提的是,它们本身有很多或(|)个。我的问题是,我最后应该做什么:将所有表达式组合成一个表达式,并使用|将它们分开,或者在单独的preg|u替换中保持它们的原样 创建其他表达式以保持清晰是非常糟糕的做法吗?我想也许我可以把一些表达组合成一个,但它们变得非常复杂,无法理解 例如,我有: $itemFullName = preg_replace("@^\b(([a-zA-Z

我必须从字符串中取出一些数据。不幸的是,数据的格式确实不友好。我必须创建大约15个正则表达式,放在单独的preg__替换中。值得一提的是,它们本身有很多或(|)个。我的问题是,我最后应该做什么:将所有表达式组合成一个表达式,并使用|将它们分开,或者在单独的preg|u替换中保持它们的原样

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

例如,我有:

$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);
我的问题是,我最后应该做什么:将所有表达式组合成一个表达式,并使用|将它们分开,或者在单独的preg|u替换中保持它们的原样

将正则表达式保留在单独的
preg_replace()
调用中,因为这样可以提高可维护性、可读性和效率

在正则表达式中使用大量OR运算符
|
对性能不友好,尤其是对于大量文本,因为正则表达式引擎必须应用于输入中的每个字符,它必须应用OR运算符的
|
列表中的每个选项。

无序: 对于初学者,您的原始PHP语句:

[0-9)0-9[0-9[1-9[0-9[0-9[0-9[0-9[0-9[0-9[0-9[0-9[10-9]1,2}(\.124?????[1,2 | 10-1,10-9[0-9[10-9[10-9[10-9[10-9[10-9[10-9[1,1,1,1,3)1,3)1,3)1,3)10[0-10[0-9[0-9[0-9[0-9[0-9[0-9[1,1,1,1,1,1,3)1,3)1,3)1,3)1,3)10[1,3)10[10[10[10[0-9[0-9[0-9[0-9[1,1,1,1,1,3]10[3[0-9]{1,3}\/[0-9]{1,3})\s@“,”$itemFullName,-1,$sum); 如果您在自由间距模式下编写它,并使用如下注释,那么它的可读性(和可维护性)会更高:

整洁的:
$itemFullName=preg_replace(“/(?#!php re_item_tidy Rev:20180207_0700)
^#锚定至管柱起点。
\字符串必须以单词char开头。
(#$1:不必要的团体。
([a-zA-Z]{1,3})#$2:可选1-3个字母。
[0-9]{1,2}#1-2位十进制数字。
(\.\-\124; X)\$3:点、连字符或X。
[0-9]{1,2}#一个或两个十进制数字。
(\s|\.|\-)?#$4:可选空白、点或连字符。
(X | X)?#5美元:可选X或X。
\s?[0-9]{1,3}\.?#可选空白,1-3位,可选点。
(#6美元:可选???来自2个备选方案。
([0-9]{1,3})?#2$7中的任意一个:可选1-3位。
(X[0-9]{1,3})#$8:X和1-3位数字。
|(#或2$9:1???来自2个备选方案。
\s[0-9]\/[0-9]\#一个或两个。
|\/[0-9]{1,3}或A2OF。
)#结束$9:1???来自2个备选方案。
)?#结束$6:可选???来自2个备选方案。
(#$10:可选序列。
\s\#[0-9]{1,3}#空格,散列,1-3位。
\/[0-9]{1,3}#正斜杠,1-3位。
)?#结束$10:可选序列
)#结束1美元:不必要的团体。
\s#以一个空格字符结尾。
/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)
^#锚定至管柱起点。
[a-zA-Z]{0,3}#可选1-3个字母。
[0-9]{1,2}#1-2位十进制数字。
[.X-]#点、连字符或X。
[0-9]{1,2}#一个或两个十进制数字。
[\s.-]?#可选空格、点或连字符。
[Xx]?#可选X或X。
\s?[0-9]{1,3}\.?#可选空白,1-3位,可选点。
(?:#可选???来自2个备选方案。
[0-9]{0,3}#任意一个A1O2:可选1-3位
X[0-9]{1,3}#后跟X和1-3位数字。
|(?:#或a2of2:1???来自2个备选方案。
\s[0-9]/[0-9]#二者之一。
|/[0-9]{1,3}#或a2of2。
)#结束2个备选方案中的一个。
)从2个备选方案中选择“结束”。
(?:#可选序列。
\s\#[0-9]{1,3}#空格,散列,1-3位。
/[0-9]{1,3}#前进