2012-11-30 22 views
4

我正在看一些代码,并开始考虑使用preg_replace截断字符串(在本例中为URI)的最有效方法。使用preg_replace截断字符串的最有效方法?

第一关 - 我意识到,摆在首位使用preg_replace可能是矫枉过正完成这个任务,它可能是不必要的昂贵,而且它可能会更好地使用PHP的字符串友好的功能来处理诸如substr。我知道这一点。

尽管如此,考虑这两个不同的正则表达式:

$uri = '/one/cool/uri'; // Desired result '/one/cool' 

// Using a back-reference 
$parent = preg_replace('#(.*)/.*#', "$1", $uri); 

// Using character class negation 
$parent = preg_replace('#/[^/]+$#', '', $uri); 

默认情况下,我会假设,在前者的情况下,创造了反向引用将是比不这样做更昂贵,为此第二个例子会更好。但是后来我开始想知道在第二个例子中使用[^/]可能比第一个例子中对应的.更昂贵,如果是这样,还有多少?

我喜欢的第一个例子从可读性的角度来看,因为我们是鸡蛋里挑骨头,我走向(以书面可读的代码过于毕竟,有值)两者之间选择它倾斜。虽然可能只是我个人的偏好。

想法?

+2

你似乎知道你在问什么,所以为什么不设置一个标杆?我的直觉也假定否定是较便宜的,但那只是我的_gut_。我没有数据支持它。制作一些数据! –

+2

注意,第二个版本可以使用占有欲量词(抑制回溯)会更高效:'#/ [^ /] + $#' –

回答

2

我也会测量两个选项的运行时间。从文档此信息可帮助过:

http://www.php.net/manual/en/regexp.reference.performance.php

如果您正在使用与不包含换行符主题串这样的模式,通过设置PCRE_DOTALL,或者开始与该模式获得最佳性能^。*表示显式锚定。这节省了PCRE不必扫描主题寻找换行符以重新启动。

因此,$parent = preg_replace('#^(.*)/.*#s', "$1", $uri);可能会加快第一个选项。第二个就不需要这个设置:

秒(PCRE_DOTALL)

如果设定了此修正,在 模式中的圆点元字符的所有字符,包括换行符相匹配。没有它, 新行被排除在外。这个修饰符相当于Perl的/ s 修饰符。 负数类如[^ a]总是匹配换行符 字符,与此修饰符的设置无关。

+0

这只会令对不图案在所有匹配的字符串的差异。如果OP知道他想要截断的每个字符串**将包含至少一个斜线,那么无论如何该匹配都将在第一次尝试中找到。 –

+0

建议的优化是避免使用换行符分割字符串,并尝试每个字符串的模式。 – Niloct

+0

啊对,对不起,够公平。我有点错过了这一点。尽管URI很少包含换行符。但总的来说,那绝对是一个好点。 –