5

我正在阅读/学习The Greatest Regex Trick Ever我们说我们想要一些东西,除非......使用(*SKIP)(*FAIL). 好的,所以我在下面的玩具示例中使用了它,它在基础 R 中工作,但在stringi中有以下错误。我是否需要对stringi做一些不同的事情才能使语法正常工作?

x <- c("I shouldn't", "you should", "I know", "'bout time")
pat <- '(?:houl)(*SKIP)(*FAIL)|(ou)'

grepl(pat, x, perl = TRUE)
## [1] FALSE  TRUE FALSE  TRUE

stringi::stri_detect_regex(x, pat)
## Error in stringi::stri_detect_regex(x, pat) : 
##   Syntax error in regexp pattern. (U_REGEX_RULE_SYNTAX)
4

1 回答 1

2

stringi模块(stringr以及)与ICU 正则表达式库捆绑在一起,(*SKIP)(*FAIL)不支持动词(它们实际上仅由 PCRE 库支持)。

由于您匹配ou的是前面h没有和后面没有的l,您可以使用通常的环视:

(?<!h)ou(?!l)

查看正则表达式演示

> x <- c("I shouldn't", "you should", "I know", "'bout time")
> pat1 <- "(?<!h)ou(?!l)"
> stringi::stri_detect_regex(x, pat1)
[1] FALSE  TRUE FALSE  TRUE

我也可以在这里提出另一种方法。由于您的代码暗示您只想返回一个布尔值,指示ou字符串中是否存在但不是houl,您可以使用

stringi::stri_detect_regex(x, "^(?!.*houl).*ou")

查看另一个正则表达式演示

细节

  • ^- 字符串的开头
  • (?!.*houl)- 如果在字符串开始之后有 0+ 个字符而不是换行符,则匹配失败的负前瞻,尽可能多地跟在后面houl
  • .*- 尽可能多的除换行符以外的 0+ 个字符
  • ou- 一个ou子串。

有关Lookahead 和 Lookbehind 零长度断言的更多详细信息。

请注意,在 ICU 中,lookbehind 不能包含未知宽度的模式,但是,支持lookbehind 内的限制量词。因此,在 中stringi,如果您想匹配包含左侧某处ou之前没有的任何单词,您可以使用s

> pat2 <- "(?<!s\\w{0,100})ou"
> stringi::stri_detect_regex(x, pat2)
[1] FALSE  TRUE FALSE  TRUE

如果(?<!s\\w{0,100}) constrained-width lookbehindou前面s有 0 到 100 个字母数字或下划线字符,则匹配失败。

于 2016-05-26T22:28:20.833 回答