preg_match基础知识问题

时间:2010-05-19 14:08:49

标签: php regex

我的preg_match遇到了一些麻烦。 代码。

$text = "tel: 012 213 123. mobil: 0303 11234 \n address: street 14";
$regex_string = '/(tel|Tel|TEL)[\s|:]+(.+)[\.|\n]/';

preg_match($regex_string , $text, $match);

我在$ match [2]

中得到了这个结果
"012 213 123. mobil: 023 123 123"

第一个问题。 我希望正则表达式停在。(点),但它是doesent。 有人可以解释为什么它不是吗?

第二个问题。 preg_match使用()来获得匹配。 是否可以跳过围绕不同“Tel”的括号并仍然获得相同的功能?

Thnx所有stackoverflow都很棒:D

5 个答案:

答案 0 :(得分:1)

这应该做:

/tel(?:\s|:)+([^.]+)(?:\.|$)/i

+是一个贪婪的量词,这意味着它会匹配尽可能多的字符。

关于第二个问题:在这种特殊情况下,您只需要使用不区分大小写的匹配(i标志)。通常,您可以使用(?:...)语法,您可以在最终匹配中看到该示例。方括号用于字符类。

答案 1 :(得分:1)

如果你只是想从这一行中提取一个电话号码,并且保证是11个号码,你可以简单地使用它:

$text = 'tel: 012 213 123. mobil: 0303 11234';
$phone_number = substr(preg_replace('/[^\d]/', '', $text), 0, 11);`

根据您的示例,$phone_number将是0122131230

这是如何工作的,任何非数字都被替换为空字符串,将其删除,然后返回前11个数字。

答案 2 :(得分:1)

不知道 - 你的正则表达式适用于我(我的代码中$match[2]得到“012 213 123”)。移动电话在两者之间存在差异这一事实可能表明它并不是您代码的输出;再次检查。

其他一些事情 - 如果你的线上有更多的点(例如“tel:xxx。phone:xxx。fax:xxx”),你会得到不好的结果 - 使用非贪婪的算子(“得到最少的”匹配“.*?而不是”获取匹配“.*的最大块”的块或限制重复的字符(“任意数量的非句点”[^.]*)。此外,你可以通过使正则表达式不区分大小写来避免麻烦(除非你真的讨厌人们输入“tEl”)。

您的另一个问题:(?:stuff)将与(stuff)匹配“内容”,但不会捕获它。

有用的链接:http://www.regular-expressions.info/

答案 3 :(得分:1)

为什么你的角色类[\.|\n][\s|:]中有管道?字符类(方括号[]中的东西)定义为OR关系,因此您不需要管道......除非您真的尝试匹配管道|

关于问题#1,我不确定你的问题是什么,但通常这与贪婪的量词有关。 (.+)量词是贪婪的,所以它尽可能匹配,同时仍然匹配整个模式。贪婪的量词并不关心模式中的后续内容。由于句点.与新行字符以外的任何字符匹配,因此它可以匹配句点,因此它与句点匹配。要使量词非贪婪,您可以使用问号?

对于您的第二个问题在RegEx中,使用括号将事物分组并存储它们。如果您要对(tel|Tel|TEL)进行分组但不将其存储在$match中,则可以在左括号后放置?:

(?:tel|Tel|TEL)

答案 4 :(得分:1)

你的意思是你想匹配这个数字,所以你不必剥离tel:和点?试试这个:

/tel[:\s]+\K[^.]+/i

i使其不区分大小写。

[:\s]匹配冒号或空格(|不代表“或”在字符类中,它只匹配|)。

[^.]+匹配一个或多个非点;当它看到一个点或行的末尾时它会停止匹配,因此如果您不希望它出现在结果中,则不必匹配该点。

最后,\K意味着“忘掉你到目前为止所匹配的任何内容,并假装比赛真的从这里开始” - 一个仅在Perl和PHP中可用的功能的宝石(我知道)