【问题标题】:Using regex to selectively extract substrings in R使用正则表达式选择性地提取 R 中的子字符串
【发布时间】:2020-10-21 13:54:02
【问题描述】:

假设我有以下字符串:

string <- c(
  "DATE_OF_BIRTH_B1",
  "HEIGHT_BABY2",
  "WEIGHT_BABY_3",
  "OTHER_CONDITION_4",
  "OTHER_OPERATION_5"
)

如何在gsub() 中使用正则表达式来提取:

  • 除尾随下划线外的所有内容,直到前三个字符串中的数字后缀;
  • 最后两个字符串中没有任何内容。

换句话说,我预期的gsub() 输出是:

"DATE_OF_BIRTH_B", "HEIGHT_BABY", "WEIGHT_BABY"

我设法使用gsub("(.+_B[A-Z]*)_?[0-9]", "\\1", string) 从前三个字符串中提取所需的子字符串,但它未能排除最后两个字符串。

任何人都可以帮助纠正和改进我的正则表达式,并提供一些解释吗?非常感谢!

【问题讨论】:

  • 您要排除的字符串是否具有某种公共性?否则,我看不出您通常如何将它们排除在外。在您的示例中,您可以例如只过滤其他。但类似的东西需要存在
  • 使用与.+的交替完成:sub("(.+_B[A-Z]*)_?[0-9]|.+", "\\1", string)

标签: r regex


【解决方案1】:

去掉OTHER或后缀。

gsub("^OTHER.*|_?[0-9]+$", "", string)
#> [1] "DATE_OF_BIRTH_B"
#> [2] "HEIGHT_BABY"    
#> [3] "WEIGHT_BABY"    
#> [4] ""               
#> [5] ""  

或者,如果您特别想要捕获组,请使用非贪婪捕获。

gsub("(OTHER.*)?(.*?)_?[0-9]", "\\2", string)
#> [1] "DATE_OF_BIRTH_B"
#> [2] "HEIGHT_BABY"    
#> [3] "WEIGHT_BABY"    
#> [4] ""               
#> [5] "" 

【讨论】:

  • 非常感谢您的解决方案!过滤“其他”是一个很好的提示,但@Wiktor Stribiżew 的解决方案可能更通用?
【解决方案2】:

如果您期望gsub(或sub,通常在这种情况下,您真的应该使用sub,因为您只期望一个替换操作)返回替换结果或空字符串,你需要遵循这个技巧:

sub("...(<what_you_want_to_extract>)...|.+", "\\1", x)

也就是说,您的正则表达式位于 | 交替运算符之前,其后跟 .+ 尽可能多地匹配任何一个或多个字符。

因此,在您的情况下,假设您的正则表达式正是您所需要的并且满足您的所有要求,您可以使用

> res <- sub("(.+_B[A-Z]*)_?[0-9]|.+", "\\1", string)
> res
[1] "DATE_OF_BIRTH_B" "HEIGHT_BABY"     "WEIGHT_BABY"     ""                ""      

如果您需要删除空项目,只需使用

> res[nzchar(res)]
[1] "DATE_OF_BIRTH_B" "HEIGHT_BABY"     "WEIGHT_BABY"

【讨论】:

  • 太棒了!非常感谢关于不要在替代字符串中捕获任何内容的提示!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-16
  • 2021-11-28
  • 1970-01-01
  • 2010-10-14
  • 1970-01-01
相关资源
最近更新 更多