【问题标题】:Converting pcre REGEX into ICU REGEX in R在R中将pcre REGEX转换为ICU REGEX
【发布时间】:2019-02-16 08:32:39
【问题描述】:

您好,我想了解如何将 PCRE REGEX 转换为 ICU REGEX,以便与 R 函数 str_match_all(stringr 包的一部分)一起使用。

@Wiktor Stribiżew 能够生成 REGEX PCRE 解析,如这些 REGEX101 演示中所示:

https://regex101.com/r/m4UD0j/17

这会解析捕获 aa 和 bb 组合(每个都以任何长度的任何数字开头)然后 cc 组(类似地以数字开头)例如10aa5bb6bb3bb6aa999cc998cc997cc

因此将字符串视为两部分:

第一个是 aa 或 bb 组合的随机集合(尽管这可能只是全部 aa,例如),前面有一个数字。

后半部分是一系列 cc(尽管这可能只是一个 cc,例如),前面有一个数字。

重要的是要同时捕获字符串的“两侧”,并且专门捕获文本和数字。所以有效的捕获是,例如:

2aa2cc
323233aa21212bb4555cc
1aa2aa3aa4aa5aa6aa117cc8cc
1bb2bb3bb4bb5bb6bb117cc8cc
1aa2bb3bb4aa5bb6bba117cc8cc
1aa2bb3bb4aa5bb6bba117cc8ccXXXXXXXXXX1aa2bb3bb4aa5bb6bba117cc8cc

无效:

2aa *Only one side of the string is there*
1aa2bb3bb4aa *Only one side of the string is there*
99cc100cc *Only one side of the string is there*

另外,我想要一个单独的 REGEX 表达式,用于“cc”组在字符串中排在第一位的情况,例如999cc998cc997cc10aa5bb6bb3bb6aa。这在此处进行了演示:https://regex101.com/r/m4UD0j/18

注意:文本模式 aa、bb 和 cc 实际上是较长字符串的缩写,因此应该这样对待。我提供了较短的版本以避免更混乱的示例。

这两个演示展示了不同组合顺序的正则表达式。

现在我必须使用 str_match_all 在 R 中运行它,不幸的是它使用了 ICU 正则表达式,而不是我们在 REGEX101 中测试的 pcre 正则表达式。

所以我有这段代码,它抛出了一个 使用尚未实现的正则表达式功能。 (U_REGEX_UNIMPLEMENTED) 错误:

#REGEX TEST#
library(stringr)

regex_text_1 <- "8aa9aa10bb1cc2cc3cc"
#reg_pattern_1 that worked in REGEX101 <- "(?:\G(?!^)(?(?=\d+(?:aa|bb))(?<!\dcc))|(?=(?:\d+(?:aa|bb))+(?:\d+cc)+))(\d+)(aa|bb|cc)"
reg_pattern_1 <- "(?:\\G(?!^)(?(?=\\d+(?:aa|bb))(?<!\\dcc))|(?=(?:\\d+(?:aa|bb))+(?:\\d+cc)+))(\\d+)(aa|bb|cc)"

regex_text_2 <- "1cc2cc3cc8aa9bb10bb"
#reg_pattern_2 that worked in REGEX101 <- "(?:\G(?!^)(?(?=\d+cc)(?<!\d(?:aa|bb)))|(?=(?:\d+cc)+(?:\d+(?:aa|bb))+))(\d+)(aa|bb|cc)"
reg_pattern_2 <- "(?:\\G(?!^)(?(?=\\d+cc)(?<!\\d(?:aa|bb)))|(?=(?:\\d+cc)+(?:\\d+(?:aa|bb))+))(\\d+)(aa|bb|cc)"

sm <- str_match_all(regex_text_1, reg_pattern_1)
sm.df <- as.data.frame(sm)
print(sm.df)

sm <- str_match_all(regex_text_2, reg_pattern_2)
sm.df <- as.data.frame(sm)
print(sm.df)

我实际上希望它输出如下内容:

    X1 X2 X3
1  8aa  8 aa
2  9aa  9 aa
3 10bb 10 bb
4 1cc  1 cc
5 2cc  2 cc
6 3cc  3 cc

    X1 X2 X3
1 1cc  1 cc
2 2cc  2 cc
3 3cc  3 cc
4  8aa  8 aa
5  9aa  9 aa
6 10bb 10 bb

...就像我们在 pcre 中应用它一样。

我不够专业,无法将代码从 pcre 转换为 icu,因此非常感谢一些帮助。非常感谢...

【问题讨论】:

    标签: r regex pcre icu


    【解决方案1】:
    data.frame(do.call(rbind,regmatches(a<-strsplit(regex_text_1,'(?<=[a-z])(?=[0-9])',perl = T)[[1]],regexec('(\\d)(\\D+)',a))))
       X1 X2 X3
    1 8aa  8 aa
    2 9aa  9 aa
    3 0bb  0 bb
    4 1cc  1 cc
    5 2cc  2 cc
    6 3cc  3 cc
    

    或在许多步骤中:

    a = strsplit(regex_text_1, '(?<=[a-z])(?=[0-9])', perl = TRUE)[[1]]
    b = regmatches(a, regexec('(\\d)(\\D+)', a))
    data.frame(do.call(rbind, b))
       X1 X2 X3
    1 8aa  8 aa
    2 9aa  9 aa
    3 0bb  0 bb
    4 1cc  1 cc
    5 2cc  2 cc
    6 3cc  3 cc
    

    您可以对regex_text_2 执行相同的操作。如果你有很多:

     ff = function(x)data.frame(do.call(rbind,regmatches(a<-strsplit(x,'(?<=[a-z])(?=[0-9])',perl = T)[[1]],regexec('(\\d)(\\D+)',a))))
    
     ff(regex_text_1)
       X1 X2 X3
    1 8aa  8 aa
    2 9aa  9 aa
    3 0bb  0 bb
    4 1cc  1 cc
    5 2cc  2 cc
    6 3cc  3 cc
    ff(regex_text_2)
       X1 X2 X3
    1 1cc  1 cc
    2 2cc  2 cc
    3 3cc  3 cc
    4 8aa  8 aa
    5 9bb  9 bb
    6 0bb  0 bb
    

    您也可以使用gsub 并执行以下操作:

    transform(read.table(text=gsub('(\\d+)(\\D+)','\\1 \\2\n',regex_text_1)),v3=paste0(V1,V2))
      V1 V2   v3
    1  8 aa  8aa
    2  9 aa  9aa
    3 10 bb 10bb
    4  1 cc  1cc
    5  2 cc  2cc
    6  3 cc  3cc
    

    【讨论】:

    • 您好。非常感谢。我已经编辑了我的问题,以便更清楚。我只需要它来捕获组合何时一起发生。所以 1cc2cc3cc 本身不会被拾取。 8aa9aa10bb 本身也不会。并且 1cc2cc3ccXXXXXXXXYYYZZZ8aa9aa10bb 将不起作用。
    • 你可以使用grep捕获指定的模式,即^(?=.*aa)(?=.*bb)(?=.*cc)(?!.*[d-z])来确定一个字符串有模式aabb`cc`并且没有来自d-z的任何其他字母
    • 这是否允许 1bb2aa3aa3cc 被解析和接受?此外,这些字母并不是真正的数据,而是模拟数据,以使示例更简单。实际上,aa 表示一个大约 10 个字符长的特定字符串。
    • 嗨@Onyambu,我的事情复杂了吗?
    【解决方案2】:

    好的,所以这不会转换为 ICU,但会更好。它是 STR_MATCH_ALL 的 Perl 版本。效果很好。

    感谢建造它的人。它来自这里:

    str_match_all_perl

    ### Parse several occurances of pattern from each of several strings
    ### using (named) capturing regular expressions, returning a list of
    ### matrices (with column names).
    str_match_all_perl <- function(string,pattern){
      stopifnot(is.character(string))
      stopifnot(is.character(pattern))
      stopifnot(length(pattern)==1)
      parsed <- gregexpr(pattern,string,perl=TRUE)
      lapply(seq_along(parsed),function(i){
        r <- parsed[[i]]
        starts <- attr(r,"capture.start")
        if(r[1]==-1)return(matrix(nrow=0,ncol=1+ncol(starts)))
        names <- attr(r,"capture.names")
        lengths <- attr(r,"capture.length")
        full <- substring(string[i],r,r+attr(r,"match.length")-1)
        subs <- substring(string[i],starts,starts+lengths-1)
        m <- matrix(c(full,subs),ncol=length(names)+1)
        colnames(m) <- c("",names)
        m
      })
    }
    

    【讨论】:

      猜你喜欢
      • 2021-03-28
      • 2016-10-25
      • 1970-01-01
      • 2015-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-07
      • 1970-01-01
      相关资源
      最近更新 更多