我正在阅读/学习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)
答案 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")
<强>详情
^
- 字符串的开头(?!.*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
约束宽度后瞻会失败。