【问题标题】:Remove any digit only in first N characters仅删除前 N 个字符中的任何数字
【发布时间】:2016-02-15 13:15:27
【问题描述】:

我正在寻找一个正则表达式来捕获字符串前 7 个字符中的所有数字。

这个字符串有 12 个字符:

A12B345CD678

我只想删除 AB,因为它们在前 7 个字符 (A12B345) 内并得到

12345CD678

因此,不应触摸CD678。我目前在 R 中的解决方案:

paste(paste(str_extract_all(substr("A12B345CD678",1,7), "[0-9]+")[[1]],collapse=""),substr("A12B345CD678",8,nchar("A12B345CD678")),sep="‌​") 

似乎太复杂了。我按照描述将字符串拆分为 7,匹配前 7 个字符中的任何数字并将其与字符串的其余部分绑定。

寻找一个普遍的答案,我目前的解决方案是拆分前 7 个字符,只匹配这个子字符串中的所有数字。

任何帮助表示赞赏。

【问题讨论】:

  • 你的问题对我来说没有任何意义。 12345CD678 超过 7 个字符,甚至超过 7 个数字 - 你说的 the first E-F 是什么意思?
  • 您的示例令人困惑。什么是“前 E-F 7 个字符”?为什么你也匹配CD,即使它们不是数字?
  • 请发布您当前的解决方案。
  • 更清楚地说,A12B345CD678 有 12 个字符。我想匹配前 7 个字符中的所有数字,因此不会触及 CD678。我目前在 R 中的解决方案: paste(paste(str_extract_all(substr("A12B345CD678",1,7), "[0-9]+ ")[[1]],collapse=""),substr("A12B345CD678",8,nchar("A12B345CD678")),sep="") 这似乎很复杂。我按照描述将字符串拆分为 7,匹配前 7 个字符中的任何数字并将其与字符串的其余部分绑定。
  • 似乎你需要可变长度的lookbehind like this demo: (?<=^.{0,6})\D,这在R regex 风格中不可用。 This could workperl=TRUE 但看起来更难维护。

标签: regex r


【解决方案1】:

您可以使用已知的SKIP-FAIL regex trick 来匹配从第 8 个字符开始的所有其余字符串,并且只匹配前 7 个中的非数字字符并进行后向查找:

s <- "A12B345CD678"
gsub("(?<=.{7}).*$(*SKIP)(*F)|\\D", "", s, perl=T)
## => [1] "12345CD678"

IDEONE demo

此正则表达式需要perl=T 才能工作。正则表达式分解:

  • (?&lt;=.{7}).*$(*SKIP)(*F) - 匹配除换行符以外的任何字符(如果输入中有换行符,请在开头添加(?s)),尽可能多地匹配(.*)直到最后($,还有\\z可能需要删除最后的换行符),但前提是前面有 7 个字符(这是由后向 (?&lt;=.{7}) 设置的)。 (*SKIP)(*F) 动词使引擎忽略整个匹配的文本并将正则表达式索引推进到该文本末尾的位置。
  • | - 或者...
  • \\D - 非数字字符。

请参阅regex demo

【讨论】:

【解决方案2】:

正则表达式解决方案很酷,但为了便于维护,我会使用更易于阅读的内容。例如

library(stringr)

str_sub(s, 1, 7) = gsub('[A-Z]', '', str_sub(s, 1, 7))

【讨论】:

  • 应该 [A-Z] 是 [A-Za-z] 吗?
【解决方案3】:

你也可以使用一个简单的否定的lookbehind:

s <- "A12B345CD678"
gsub("(?<!.{7})\\D", "", s, perl=T)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-30
    • 2016-01-09
    • 2019-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-05
    相关资源
    最近更新 更多