(跳过)(失败)用stringi解析错误

时间:2016-01-14 22:49:45

标签: regex r stringi

我正在阅读/学习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)

1 个答案:

答案 0 :(得分:2)

stringi模块(以及stringr)与ICU regex library捆绑在一起,(*SKIP)(*FAIL)动词不受支持(实际上只有PCRE库支持它们)。

由于您匹配的ou前面没有h且未跟l,因此您可以使用常规的外观:

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

请参阅regex demo

> 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")

请参阅another regex demo

<强>详情

  • ^ - 字符串的开头
  • (?!.*houl) - 如果在字符串开头之后,匹配失败,那么除了换行符之外还有0 +字符,尽可能多地跟着houl
  • .* - 除尽可能多的换行符之外的0 +字符
  • ou - ou子字符串。

有关Lookahead and Lookbehind Zero-Length Assertions的更多详情。

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

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

如果(?<!s\\w{0,100})前面有ou,后跟0到100个字母数字或下划线字符,那么s 约束宽度后瞻会失败。