strsplit 和 stri_extract_all_regex 的贪婪性

问题描述 投票:0回答:1

我正在努力让

strsplit
stri_extract_all_regex
始终如一地工作。按 strsplit 拆分是所需的行为(实际上,我有一长串由代码动态生成的替代匹配)。

例如

strsplit("1234567","(23)|(234)")
[[1]]
[1] "1"   "567"

stri_extract_all_regex("1234567","(23)|(234)")
[[1]]
[1] "23"

提取所需的输出是

[[1]]
[1] "234"
r regex strsplit
1个回答
0
投票

PCRE vs ERE vs ICU

这取决于所使用的正则表达式引擎。 Base R 默认使用扩展正则表达式 (ERE),或Perl 兼容正则表达式 (PCRE)。相反,“stringi”[文档] 指出了这一点:

提供对 ICU 中实现的正则表达式引擎的访问,该引擎的灵感来自于 JDK 1.4 中的 Java

util.regex

我们可以看到它的实际效果:

library(stringi)
x <- "1234567"
pattern <- "(23)|(234)"

# Base R (ERE) engine
regmatches(x, gregexpr(pattern, x))  |> unlist()
# [1] "234"

# Base R (PCRE) engine
regmatches(x, gregexpr(pattern, x, perl = TRUE))  |> unlist()
# [1] "23"

stri_extract_all_regex(x, pattern)  |> unlist()
# [1] "23"

但是,如果我们改变顺序

pattern <- "(234)|(23)"
,它们都会返回
234

排列您的模式,使最长的匹配位于第一个

动态生成模式后,您可以编写一个函数来按最长的优先顺序对其模式进行排序。

switch_pattern_order  <- function(pattern){
    pattern_split  <- unlist(strsplit(pattern, "|", fixed = TRUE))
    pattern_sorted  <- pattern_split[rev(order(nchar(pattern_split)))]
    new_pattern  <- paste(pattern_sorted, collapse = "|")
    new_pattern
}
pattern  <- switch_pattern_order(pattern) # "(234)|(23)"
regmatches(x, gregexpr(pattern, x))  |> unlist()
# [1] "234"

regmatches(x, gregexpr(pattern, x, perl = TRUE))  |> unlist()
# [1] "234"

stri_extract_all_regex(x, pattern)  |> unlist()
# [1] "234"
© www.soinside.com 2019 - 2024. All rights reserved.