【问题标题】:How do I match a string until certain pattern that also works when the pattern does not show up?我如何匹配一个字符串,直到某个模式在模式不出现时也可以工作?
【发布时间】:2023-03-30 10:12:01
【问题描述】:

我需要提取数字后跟一个 A,直到出现模式“X”:

"50A ABC DE 51A FG X 52A HI 53A"

正则表达式\d+A(?=.* X ) 正确匹配50A51A,因为它们出现在X 之前 ,如图here

但是,如果字符串不具有 X 模式,则正则表达式将不会匹配任何所需的模式(50A、51A、52A 和 53A)

"50A ABC DE 51A FG 52A HI 53A"    # no X here

我该如何解决这个问题?

【问题讨论】:

    标签: r regex


    【解决方案1】:

    您可以使用 PCRE 正则表达式,例如

    \G(?:(?! X ).)*?\K\b\d+A\b
    

    请参阅regex demo详情

    • \G - 字符串开始或上一个成功匹配的结束(仅确保连续匹配)
    • (?:(?! X ).)*? - 任何不以空格开头的字符,除了换行字符,尽可能少+X+空格字符序列
    • \K - 一个匹配重置操作符,丢弃目前匹配的所有文本
    • \b\d+A\b - 一个或多个数字和A 在字边界内。

    在 R 中,你可以使用the following base R code:

    x <- "50A ABC DE 51A FG 52A HI 53A"
    rx <- "\\G(?:(?! X ).)*?\\K\\b\\d+A\\b"
    regmatches(x, gregexpr(rx, x, perl=TRUE))
    # => [[1]]
    #    [1] "50A" "51A" "52A" "53A"
    x <- "50A ABC DE 51A FG X 52A HI 53A"
    regmatches(x, gregexpr(rx, x, perl=TRUE))
    # => [[1]]
    #    [1] "50A" "51A"
    

    你可以把X之后的全部去掉,然后提取:

    x <- "50A ABC DE 51A FG X 52A HI 53A"
    library(stringr)
    str_extract_all(sub("(\\s|^)X(\\s.*)?$", "", x), "\\b\\d+A\\b")
    # => [[1]]
    #    [1] "50A" "51A"
    
    x <- "50A ABC DE 51A FG 52A HI 53A"
    str_extract_all(sub("(\\s|^)X(\\s.*)?$", "", x), "\\b\\d+A\\b")
    # => [[1]]
    #    [1] "50A" "51A" "52A" "53A"
    

    这里,

    • sub("(\\s|^)X(\\s.*)?$", "", x) 删除字符串开头或空格(带有此空格)之后的 X,并可选择在字符串末尾添加空格和任何文本
    • str_extract_all(..., "\\b\\d+A\\b") 提取一个或多个数字,后跟 A 作为剩余字符串部分中的整个单词。

    【讨论】:

      【解决方案2】:

      另一个选项可能是匹配 X 并且从那时起避免使用 SKIP FAIL 匹配其余类似选项并使用 perl=T 启用 PCRE

      X .*(*SKIP)(*F)|\b\d+A\b
      

      模式匹配:

      • X 字面匹配
      • .*(*SKIP)(*F)匹配该行的其余部分以避免匹配它
      • |或者
      • \b\d+A\b 在单词边界之间匹配 1+ 个数字和 A

      查看regex demoR demo

      例子

      library(stringr)
      
      s1 <- "50A ABC DE 51A FG X 52A HI 53A"
      s2 <- "50A ABC DE 51A FG 52A HI 53A"
      patt <- "X .*(*SKIP)(*F)|\\b\\d+A\\b"
      
      regmatches(s1, gregexpr(patt, s1, perl=T))
      regmatches(s2, gregexpr(patt, s2, perl=T))
      

      输出

      [[1]]
      [1] "50A" "51A"
      
      [[1]]
      [1] "50A" "51A" "52A" "53A"
      

      【讨论】:

        猜你喜欢
        • 2020-03-27
        • 1970-01-01
        • 1970-01-01
        • 2012-04-24
        • 1970-01-01
        • 1970-01-01
        • 2016-10-03
        • 2021-04-10
        • 1970-01-01
        相关资源
        最近更新 更多