【问题标题】:Maintain specific string portions when matching regex匹配正则表达式时维护特定的字符串部分
【发布时间】:2020-05-10 05:32:00
【问题描述】:

考虑以下玩具示例:

a <- c(rep(1,3))
b <- c(rep("b", 3))
names <- c("2019 Report", "XYZ Report", "2018 Report")
df <- as.data.frame(cbind(a, b, names))

我想修改names 列中的字符串,但仅限于包含年份的名称:

names_desired <- c("2019 Good Report", "XYZ Report", "2018 Good Report")
df_target <- as.data.frame(cbind(a, b, names, names_desired))

有很多方法可以通过过滤掉不包含年份的名称来做到这一点,例如(排序无关):

df %>% 
  filter(str_detect(names, "[:digit:]") == FALSE) %>% 
  mutate(names_desired = names) %>% 
  bind_rows(df %>% 
              filter(str_detect(names, "[:digit:]") == TRUE) %>% 
              mutate(names_desired = str_replace(names, "Report", "Good Report")))

我想要的是一种将名称与正则表达式匹配的方法,就像这样(不起作用):

df %>% 
  mutate(names_desired = str_replace(names, "[:digit:]{4} Report", "[:digit:]{4} Good Report"))

理想情况下,"[:digit:]{4}" 会返回匹配的数字,当然它不会。有没有办法做到这一点?

【问题讨论】:

    标签: r regex tidyverse stringr


    【解决方案1】:

    一种选择是将捕获作为一个组 ((...)),然后替换为反向引用(\\1\\2 - 基于捕获组的顺序)

    library(dplyr)
    library(stringr)
    df <- df %>%
       mutate(names_desired = str_replace(names, '(\\d{4}) (Report)', '\\1 Good \\2'))
    df
    #    a b       names    names_desired
    #1 1 b 2019 Report 2019 Good Report
    #2 1 b  XYZ Report       XYZ Report
    #3 1 b 2018 Report 2018 Good Report
    

    在这种情况下,“报告”是固定的,所以我们只需要捕获一个组

    df %>%
       mutate(names_desired = str_replace(names, '(\\d{4}) Report', '\\1 Good Report'))
    

    或使用base R

    sub("(\\d{4}) (Report)", "\\1 Good \\2", df$names)
    #[1] "2019 Good Report" "XYZ Report"       "2018 Good Report"
    

    数据

    df <- data.frame(a, b, names)
    

    【讨论】:

    • 非常好 - 禁运结束后我会接受。同时,您可以将其编辑为'\\1 Good \\2',因为只有两个反向引用吗?无法更改编辑中的一个字符...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-15
    • 1970-01-01
    • 2021-11-30
    • 2013-12-12
    • 2012-11-25
    • 2015-10-25
    相关资源
    最近更新 更多