我有一个正则表达式列表,我想应用于字符串,这样我就可以看到哪些正则表达式匹配字符串。我考虑过将这些独立的正则表达式折叠成一个,然后使用捕获组来知道哪个正则表达式匹配字符串。例如,我可以先执行grepl("a", "foo")
,然后再执行grepl("b", "foo")
,然后使用capture.start
属性来知道哪个正则表达式匹配。
在下面的例子中,我有两个正则表达式("^a"
和"cyprus"
)和一个要匹配的字符串("Cyprus"
)。如果我在原始的正则表达式中还没有组,这可以很好地工作:
x <- gregexpr("(^a)|(cyprus)", "Cyprus", perl = TRUE, ignore.case = TRUE)[[1]]
attr(x, "capture.start")
#>
#> [1,] 0 1
假设现在我在第一个正则表达式中已经有了一个组,所以它不再是"^a"
,而是"^a(b|a)"
。然后我得到了比我想要的更多的组:
x <- gregexpr("(^a(b|a))|(cyprus)", "Cyprus", perl = TRUE, ignore.case = TRUE)[[1]]
attr(x, "capture.start")
#>
#> [1,] 0 0 1
在上面的例子中,它返回3个组,因为第一个组包含两个“子组”。我希望只得到“top groups”的结果,而不是“subgroups”,这样上面的输出就只有0 1
。有办法做到吗?
我正在寻找一个解决方案,在 * 基地R只 *,而不是使用stringr
/stringi
。
**编辑:**按照@user2554330的回答,我为每个正则表达式生成一个随机id。然而,当正则表达式的数量大于127时,我会出现一个错误:
append_unique_id <- function(x) {
for (i in seq_along(x)) {
x[i] <- paste0("<", paste(sample(letters, 10), collapse = ""), ">", x[i])
}
x
}
list_regexes <- sample(letters, 128, TRUE) # <<<<<<<<<<< change this to
# 127 and it works
regex2 <- append_unique_id(list_regexes)
regex2 <- paste0("(?", regex2, ")")
regex2 <- paste(regex2, collapse = "|")
out <- gregexpr(regex2, "Cyprus", perl = TRUE, ignore.case = TRUE)
#> Error in gregexpr(regex2, "Cyprus", perl = TRUE, ignore.case = TRUE): attempt to set index -129/128 in SET_STRING_ELT
3条答案
按热度按时间jv4diomz1#
你可以使用“命名捕获”。仅将名称应用于顶级组,而不是任何嵌套组。比如说,
创建于2023-09-04使用reprex v2.0.2
根据你想对结果做什么,你可以按名称索引,或者删除任何未命名的结果,例如。
创建于2023-09-04使用reprex v2.0.2
oewdyzsn2#
我认为这比简单地在正则表达式向量上使用
sapply
要复杂得多。它可以在一行代码中完成所有你想要的事情。此外,您不会对所需的正则表达式的数量有任何限制,并且您不需要将所有正则表达式引入到一个模式中。nnsrf1az3#
如果我理解正确的话,你有一个正则表达式列表,你想看看它们中的每一个是否匹配给定的主题,对吗?在这种情况下,您需要使用grepl + for循环或sapply,因为gregexpr +一个带有捕获组替换的正则表达式不会做同样的事情。交替使正则表达式引擎消耗第一个匹配的交替,然后在找到第一个匹配后停止尝试匹配其他交替。例如,如下所示,两个正则表达式都匹配,但gregexpr正确地说只有第一个捕获组匹配,grepl正确地说每个正则表达式都匹配主题。