阅读R4DS字符串一章,对以下正则表达式示例感到困惑:
x <- "1888 is the longest year in Roman numerals: MDCCCLXXXVIII"
str_view(x, "C?")
此代码未返回匹配项
我理解使用?
指定匹配0或1次,并且重复是“贪婪的”,并且将匹配可能的最长字符串,那么为什么不匹配1个“ C”呢?
此外,以下代码与第一个“ CC”匹配:
x <- "1888 is the longest year in Roman numerals: MDCCCLXXXVIII"
str_view(x, "CC?")
谢谢
答案 0 :(得分:3)
我认为它确实返回了一个匹配项,但这是空字符串。
说明:
M
与C
不匹配。C
是可选的。另一方面,CC?
在字符串的开头无法匹配,因此引擎必须逐步遍历字符串,直到找到第一个C
,然后无论如何匹配都将匹配有C
个。
道德的:切勿在所有标记都是可选的情况下构造正则表达式,以允许为空匹配(除非您打算做到这一点)。
答案 1 :(得分:3)
这是因为正则表达式引擎会在可能的情况下放弃。仅需一个可选字符,您就不需要任何要求。正则表达式在位置0处得到满足,尝试并没有找到“ C”,但是它是可选的。
使用这两个字符,硬的“ C”会强制引擎向右移动,因为您实际上是在问什么,而第二个“ C”是下一个(可选)字符,因此会被抛出。 / p>
答案 2 :(得分:2)
RewriteRule
有一个匹配项,但长度为0。使用基R的函数RewriteRule
分析此行为很有帮助。
RewriteEngine On
RewriteCond %{REQUEST_URI} !\.(txt) [OR]
RewriteCond %{REQUEST_URI} robots\.txt
RewriteCond %{REQUEST_URI} !acme
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{REQUEST_URI} !\.(txt) [OR]
RewriteCond %{REQUEST_URI} robots\.txt
RewriteCond %{HTTPS} !=off
RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
这表明匹配从位置1开始,长度为0。由于str_view(x, "C?")
表示regexpr
一次或零次,因此它与{{1}开头的空字符串匹配}。
regexpr("C?", x)
# [1] 1
# attr(,"match.length")
# [1] 0
# attr(,"useBytes")
# [1] TRUE
相反,正则表达式C?
匹配从位置47开始的长度为2的字符串。由于第一个C
是必需的,因此它不能匹配空字符串。由于x
是贪婪的,所以regexpr("CC?", x)
# [1] 47
# attr(,"match.length")
# [1] 2
# attr(,"useBytes")
# [1] TRUE
与CC?
的第一个C
和第二个?
都匹配。