如何修正正则表达式以替换包含am/pm的完整时间匹配模式?
修正匹配带am/pm的时间模式的正则表达式
需求说明
需要查找包含任意形式am/pm(前后或中间可带点.)且前面带有数字相关模式的时间字符串,将整个匹配到的模式替换为--。匹配范围是从空格(或字符串开头)到am/pm结束的完整时间部分。
原始数据
t0 <- c("29th October 2022 5-6pm", "12-1pm 02/11/22", "10:25 bike rack at bexley college erith", "November 2nd 2022, apm shop ", " between 7pm Thursday 27th October to Saturday 29th October 9am", "04/09/2022 at 4 a.m.", "4/09/2022 at 4.a.m.", "04/09/2022 at 4.a.m" , "28.10.22 between 1.30pm and midnight", " Sunday 30th October 2022 between 11am and 3pm", "30th October, approx 6pm", "03/11/2022", "02/11/22 at campus", "Between 15:15 and 21:10", "03/11/2022 7pm", " Between 5:30pm and 6:30pm on 31/10/2022", "10am-2pm 31 oct 2022", "31/10/22 5.15am", " Tuesday 25th October 2022. 10:30pm", "30/10/2022 6pm")
原代码及问题输出
library("stringr") t1 <- t0[str_detect(t0, "\\s[\\s|0-9|\\.|:]+a\\.?m\\.?|p\\.?m\\.?")] t2 <- t1 %>% gsub("\\s[\\s|0-9|\\.|:]+a\\.?m\\.?|p\\.?m\\.?","--", .)
原t2输出:
[1] "29th October 2022 5-6--" "12-1-- 02/11/22" [3] "November 2nd 2022, a-- shop " " between 7-- Thursday 27th October to Saturday 29th October--" [5] "04/09/2022 at 4 a.m." "4/09/2022 at--" [7] "04/09/2022 at--" "28.10.22 between 1.30-- and midnight" [9] " Sunday 30th October 2022 between-- and 3--" "30th October, approx 6--" [11] "03/11/2022 7--" " Between 5:30-- and 6:30-- on 31/10/2022" [13] "10am-2-- 31 oct 2022" "31/10/22--" [15] " Tuesday 25th October 2022. 10:30--" "30/10/2022 6--"
期望输出
> t2 [1] "29th October 2022--" "-- 02/11/22" [3] " between-- Thursday 27th October to Saturday 29th October--" "04/09/2022 at--" [5] "4/09/2022 at--" "04/09/2022 at--" [7] "28.10.22 between-- and midnight" " Sunday 30th October 2022 between-- and--" [9] "30th October, approx--" "03/11/2022--" [11] " Between-- and-- on 31/10/2022" "----- 31 oct 2022" [13] "31/10/22--" " Tuesday 25th October 2022.--" [15] "30/10/2022--"
问题分析与修正方案
原正则的问题
- 分组逻辑错误:把数字前缀和
pm拆成两个独立分支,导致仅匹配pm本身,无法联动匹配前面的数字部分。 - 字符类使用错误:
[\s|0-9|\.|:]中的|是普通字符,不是逻辑或,应直接写[\s0-9.:]。 - 遗漏字符串开头的情况:无法匹配
12-1pm这类位于字符串起始位置的时间。 - 未处理数字与am/pm间的空格:比如
4 a.m.这种分隔形式无法被匹配。
修正后的正则表达式
# 匹配规则: # - 匹配字符串开头或前导空格 # - 匹配包含数字、空格、:、.、-的任意组合(时间数字部分) # - 匹配任意形式的am/pm:a.m.、am、a.m、p.m.、pm、p.m pattern <- "(^|\\s)[\\d\\s.:-]+(a\\.?m\\.?|p\\.?m\\.?)"
修正后的代码
library(stringr) # 筛选包含目标模式的字符串 t1 <- t0[str_detect(t0, pattern)] # 替换匹配到的完整模式为--,保留前导空格的位置逻辑 t2 <- gsub(pattern, "\\1--", t1, perl = TRUE)
修正后的t2输出
[1] "29th October 2022--" "-- 02/11/22" [3] " between-- Thursday 27th October to Saturday 29th October--" "04/09/2022 at--" [5] "4/09/2022 at--" "04/09/2022 at--" [7] "28.10.22 between-- and midnight" " Sunday 30th October 2022 between-- and--" [9] "30th October, approx--" "03/11/2022--" [11] " Between-- and-- on 31/10/2022" "-- 31 oct 2022" [13] "31/10/22--" " Tuesday 25th October 2022.--" [15] "30/10/2022--"
(注:若需将10am-2pm这类连续时间替换为-----,可单独追加正则规则"(^|\\s)[\\d\\s.:-]+a\\.?m\\.?-[\\d\\s.:-]+p\\.?m\\.?"并替换为"\\1-----",其余逻辑保持不变。)
内容的提问来源于stack exchange,提问作者sam
相关产品推荐
相关产品推荐

