【问题标题】:gsub returning more than regex matchgsub 返回超过正则表达式匹配
【发布时间】:2017-08-16 18:48:45
【问题描述】:

我有这样的字符串

x = c(
"blahblah, blah blah, Plate 3, blah blah"
,
"blah blah, blah_Plate 2_blah, blah"
,
"blah, blah, blah blah, blah plate_3"
,
"blah blah, blah, plate 5.txt"
)

我想从所有这些文件名中获取车牌号,

所以我正在测试我的正则表达式匹配

 gsub("\\<Plate\\>.[0-9]","\\1",workdf_nums_plats$Bioplex_Files)

所以我最终可以做这样的事情

workdf_nums_plats$plat <- ifelse(grepl("\\<Plate\\>.[0-9]", workdf_nums_plats$Bioplex_Files), gsub("\\<Plate\\>.[0-9]","\\1",workdf_nums_plats$Bioplex_Files), NA)

我正在返回整个字符串,我尝试使用 \b 设置单词边界,但这没有帮助。

任何建议都会非常感谢!

【问题讨论】:

  • 您似乎发现这些答案很有帮助。考虑接受对您最有帮助的一项(答案左侧的复选标记)。

标签: r regex


【解决方案1】:

您需要在内部定义一个捕获组并以不区分大小写的方式匹配plate,但不是整个单词,因为您需要在_之后匹配它(它也是一个单词char):

workdf_nums_plats$plat <- sub(".*?Plate.([0-9]+).*","\\1", workdf_nums_plats$Bioplex_Files, ignore.case=TRUE)

查看regex demo 和下面的 R 演示:

Bioplex_Files <- c("blahblah, blah blah, Plate 3, blah blah", "blah blah, blah_Plate 2_blah, blah", "blah, blah, blah blah, blah plate_3", "blah blah, blah, plate 5.txt")
plat <- sub(".*?Plate.([0-9]+).*","\\1", Bioplex_Files, ignore.case=TRUE)
plat
## => [1] "3" "2" "3" "5"

模式详情

  • .*? - 任何 0+ 个字符,尽可能少
  • Plate - plate 子字符串(ignore.case=TRUE 不区分大小写)
  • . - 任何字符
  • ([0-9]+) - 第 1 组(使用替换模式中的 \1 反向引用)匹配 1 个或多个数字
  • .* - 任何 0+ 个字符,直到字符串结尾。

如果您想将Plate 匹配为一个完整的单词,您可以在Plate 前面加上(?:_|\b) 模式".*?(?:_|\\b)Plate.([0-9]+).*"。这里,(?:_|\b) 是一个匹配_ 或单词边界的非捕获组(即它不会创建$2$1 等)。

另一种解决方案是匹配您需要的值,为此目的使用stringr很方便:

> str_extract(Bioplex_Files, "(?i)(?<=Plate.)[0-9]+")
[1] "3" "2" "3" "5"

这里,(?i) 是一个不区分大小写的标志,(?&lt;=Plate.) 是一个肯定的后视,它断言有 Plate 和紧接在 [0-9]+ 之前的任何字符 - 1 个或多个数字(并且只有数字是由于后向模式是零长度断言,即它不会将文本添加到匹配值中,因此返回)。

【讨论】:

  • 感谢您帮助我了解自己的解决方案并提供替代解决方案!
  • @AwesomeeExpress 只是想让您知道您也可以使用str_match(Bioplex_Files, "(?i)(?:_|\\b)Plate.([0-9]+)")[,2]。很高兴能提供帮助。
【解决方案2】:

一种方法是使用regmatchesregexec 来返回捕获的子表达式。

regmatches(test, regexec("[Pp]late.?([0-9]+)", test))
[[1]]
[1] "Plate 3" "3"      

[[2]]
[1] "Plate 2" "2"      

[[3]]
[1] "plate_3" "3"      

[[4]]
[1] "plate 5" "5" 

这里,[Pp] 将匹配“P”或“p”,“late”按字面意思匹配自身,“.?”匹配任何字符的 0 或 1,“()”捕获所需的值,即“[0-9]+”,一个或多个数字。

由于这会返回一个列表,因此您想使用sapply 从每个列表项中提取第二个元素,就像这样。

sapply(regmatches(test, regexec("[Pp]late.?([0-9]+)", test)), "[", 2)
[1] "3" "2" "3" "5"

数据

test <- 
c("blahblah, blah blah, Plate 3, blah blah", "blah blah, blah_Plate 2_blah, blah", 
"blah, blah, blah blah, blah plate_3", "blah blah, blah, plate 5.txt")

【讨论】:

  • 谢谢!您的解决方案比我的更优雅,正则表达式非常...深!
猜你喜欢
  • 1970-01-01
  • 2022-01-14
  • 1970-01-01
  • 1970-01-01
  • 2015-11-30
  • 1970-01-01
  • 2021-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多