【问题标题】:Regex help, subset based on nth occurance from the end of string正则表达式帮助,基于字符串末尾第 n 次出现的子集
【发布时间】:2021-12-27 02:36:38
【问题描述】:

一个示例向量:

string <- "Junk1_Junk2_Junk3__ID1_Junk4_Junk5.pdf"

我试图通过从右边数 _(下划线)来对 ID1 进行子集化;所以从右边数第二个和第三个下划线之间的子集。

预期输出:ID1

我的尝试是尝试使用双重__, 但这行不通,因为不是我的所有字符串列表都有它。

尝试:(_){2}([^_]+)

旁注,我正在努力适应正则表达式;请推荐一个资源来构建和测试。

感谢任何帮助。

【问题讨论】:

  • 你的预期结果是什么?
  • 编辑帖子:预期结果 = 'ID1'
  • 快速拍摄:gsub("(.*?_){3}(.*)(_.*?){2}.*", "\\2", string)?

标签: r regex


【解决方案1】:

你可以使用

library(stringr)
stringr::str_extract(string, "[^_]+(?=(?:_[^_]*){2}$)")

或者,与基础 R 相同的方法:

## Base R:
sub(".*?([^_]+)(?:_[^_]*){2}$", "\\1", string)

请参阅 regex demoR demo online

详情

  • [^_]+ - 除了_ 之外的一个或多个字符
  • (?=(?:_[^_]*){2}$) - 一个正向前瞻,需要两个_ 序列,然后是_ 以外的任何字符的零个或多个重复,直到字符串结束
  • .*?([^_]+)(?:_[^_]*){2}$ 匹配
    • .*? - 任何零个或多个字符,尽可能少
    • ([^_]+) - 捕获组 1(替换模式中的\1 指的是这个捕获的字符串):除_ 之外的一个或多个字符
    • (?:_[^_]*){2} - _ 的两个序列,然后是 _ 以外的任何字符的零个或多个重复
    • $ - 字符串结束。

【讨论】:

  • 非常好。可以使用这种细微的变化来更好地允许多个 _ 作为分隔符[^_]+(?=(?:_+[^_]+){2}$)
  • @Daniel 是的,+ 表示一个或多个* 表示零个或多个。必要时使用。
【解决方案2】:
sub(".*_([^_]+)(_[^_]+){2}", "\\1", string)
[1] "ID1"

【讨论】:

    【解决方案3】:

    我曾想过在纯正则表达式中执行此操作,但我认为我实际上会在 R 中简化这个问题。我将使用一些非常简单的正则表达式和两个 R 命令而不是 1。

    str_extract(string,"[^_]+_[^_]+_[^_]+$") %>% 
      str_remove("_[^_]+_[^_]+$")
    

    我在这里找到了非下划线 [^_]+ 和下划线 _ 的组合。

    为了便于正则表达式,我提取了整个字符串。然后我去掉多余的。

    或者,我们可以使用更复杂的正则表达式和前瞻方法。

    str_extract(string,"[^_]+(?=_[^_]+_[^_]+$)")
    

    我认为对于许多不经常使用 Regex 的编码人员来说,前瞻代码更易于阅读。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多