提问人:asimes 提问时间:1/18/2014 最后编辑:asimes 更新时间:1/20/2014 访问量:17542
正则表达式“匹配”与“捕获”
Regular Expression "Matching" vs "Capturing"
问:
我一直在查找正则表达式教程,试图掌握它们的窍门,并且一直很喜欢此链接中的教程,直到出现此问题:http://regexone.com/lesson/12
我似乎无法弄清楚“匹配”和“捕获”之间的区别是什么。我写的任何内容似乎都没有选择“捕获”部分下的文本(甚至没有)。.*
编辑:这是一个让我感到困惑的教程示例:被认为是正确的,而不是。这是教程的问题还是我不理解的地方?(.* (.*))
(.* .*)
答:
看看这 2 个正则表达式 - 从您的示例中
# first
/(... (\d\d\d\d))/
#second
/... \d\d\d\d/
它们都匹配“Jun 1965”和“May 2000”
(顺便说一句,还有许多其他内容,例如“555 1234”)
第二个正好匹配它 - Yesno
所以你可以说
if ($x=~/... \d\d\d\d/){do something}
第一个捕捉到了
/(... (\d\d\d\d))/
print $1,";;;",$2
将打印“Jun 1967;;;1967"
评论
...
$1
$2
$1
$2
$
$1
... \d\d\d\d
$2
\d\d\d\d
$1
$2
$3
(.).\1
\1
$1
在正则表达式中捕获意味着表明您不仅对匹配感兴趣(即查找与正则表达式匹配的字符串),而且您还对以后使用匹配字符串的特定部分感兴趣。
例如,您链接到的教程的答案是 。(\w{3}\s+(\d+))
现在,为什么?
为了简单地匹配日期字符串,写(3 个单词字符,后跟一个或多个空格,后跟一个或多个数字)就足够了,但是将捕获组添加到表达式中(捕获组只是括在括号中的任何内容)将允许我稍后提取整个表达式(使用“$1”,因为最外侧的一对括号是解析器遇到的第一个)或仅提取年份(使用“$2”, 因为括号中的第二对,在 周围,是正则表达式解析器遇到的第二对)\w{3}\s+\d+
()
\d+
当您不仅对将字符串与模式匹配感兴趣,而且还对从匹配的字符串中提取数据或以任何方式修改它们感兴趣时,捕获组会派上用场。例如,假设您想在本教程中为每个日期添加 5 年 - 能够从匹配的字符串中提取年份部分(使用 )会派上用场$2
评论
$1
$2
matches
匹配:
当 engine 匹配字符串的一部分或整体但不返回任何内容时。
捕获:
当 engine 匹配字符串的一部分或整体并返回某些内容时。
-- 返回的意义是什么?
当您需要检查/存储/验证/工作/爱正则表达式匹配的字符串的一部分时,您需要捕获组 (...)
在您的示例中,此正则表达式仅匹配日期和年份 请参阅此处.*?\d+
这个正则表达式匹配整体并捕获年份 看这里.*?(\d+)
并将匹配整体并分别捕获整体和年份 看这里(.*?(\d+))
*请注意右下角标题为“匹配组”的框
所以回来了......
1:
preg_match("/.*?\d+/", "Jan 1987", $match);
print_r($match);
输出:
Array
(
[0] => Jan 1987
)
2:
preg_match("/(.*?\d+)/", "Jan 1987", $match);
print_r($match);
输出:
Array
(
[0] => Jan 1987
[1] => Jan 1987
)
3:
preg_match("/(.*?(\d+))/", "Jan 1987", $match);
print_r($match);
输出:
Array
(
[0] => Jan 1987
[1] => Jan 1987
[2] => 1987
)
因此,正如您在最后一个示例中看到的,我们有 2 个捕获组,索引分别为 1 和 2,并且 0 始终是匹配的字符串,但它没有被捕获。
评论
?
(.*?(\d+))
(.*(\d+)
/.*?\d+/
简而言之,“捕获”将收集的值保存在一个特殊位置,以便您以后可以访问它。
正如一些人所指出的,捕获的东西可以“稍后”以相同的模式使用,因此
/(ab*c):\1/
将匹配 ac:ac、abc:abc 或 abbc:abbc 等。(ab*c) 将匹配 a,b,然后是 c。无论它匹配什么,都会被“捕获”。在许多编程和脚本语言中,像 \1、\2 等语法具有特殊的含义,指的是第一个、第二个等捕获。由于第一个可能是 abbc,因此 \1 位必须仅匹配 abbc,因此唯一可能的完全匹配将是“abbc:abbc”
Perl(我认为)PHP 都允许 \1 \2 语法,但它们也使用 $1 $2 等,这被认为更现代。许多语言已经从Perl中采用了强大的正则表达式引擎,因此世界上越来越多地使用它。
由于您的示例问题似乎在 PHP 网站上,因此 PHP 中 1 美元的典型用途是:
/(ab*c)(de*f)/
然后稍后(例如下一行代码)
$x = $1 . $2; # I hope that's PHP syntax for concatenation!
因此,在您下次使用正则表达式之前,捕获是可用的。根据所使用的编程语言,这些捕获的值可能会被下一个模式匹配所破坏,或者它们可能通过特殊语法或语言的使用永久可用。
评论
上一个:故意返回 NaN
评论
([a-z])\1
(...)
\1
\1
(...)