R正则表达式重复

时间:2018-12-04 08:01:41

标签: r regex

阅读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?")

谢谢

3 个答案:

答案 0 :(得分:3)

我认为它确实返回了一个匹配项,但这是空字符串。

说明:

  1. 正则表达式引擎首先检查第一个字符是否匹配
  2. MC不匹配。
  3. 但是,C是可选的。
  4. 空字符串匹配。
  5. 成功!

另一方面,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和第二个?都匹配。