【问题标题】:Extract a numeric value of a specific length from string in R using regex使用正则表达式从 R 中的字符串中提取特定长度的数值
【发布时间】:2019-12-26 09:13:36
【问题描述】:

看起来像一个重复的问题,但其他答案对我没有帮助。我正在尝试提取文本中的任何 8 位数字。该数字可以在文本中的任何位置。它可以是独立的,也可以是跟随或被字符串跟随。基本上,我需要从 R 中的字符串中提取任何出现的 8 个连续数字字符,仅使用正则表达式。

这是我尝试但无济于事的:

> my_text <- "the number 5849 and 5555555555 shouldn't turn up. but12345654 and 99119911 should be. let's see if 1234567H also works. It shouldn't. both 12345678JE and RG10293847 should turn up as well."

> ## this doesn't work
    > gsub('(\\d{8})', '\\1', my_text)
    [1] "the number 5849 shouldn't turn up. but12345654 and 99119911 should be. let's see if 1234567H also works. It shouldn't.both 12345678JE and RG10293847 should turn up as well."

我想要的输出应该提取以下数字:

12345654
99119911 
12345678
10293847

同时,如果答案包括第二个正则表达式,用于仅提取第一次出现的 8 位数字,我将不胜感激:

12345654

编辑:我有一个非常大的表(大约 2 亿行),我需要在一个列上对其进行操作。什么是最有效的解决方案?

编辑:我意识到我的文本案例中缺少案例。文本中还有一些数字长度超过 8 位,但我只想提取正好是 8 位的数字。

【问题讨论】:

    标签: r regex extract gsub string-length


    【解决方案1】:

    我们可以使用str_extract_all

    stringr::str_extract_all(my_text, "\\d{8}")[[1]]
    #[1] "12345654" "99119911" "12345678" "10293847"
    

    同样,在基础 R 中,我们可以使用 gregexprregmatches

    regmatches(my_text, gregexpr("\\d{8}", my_text))[[1]]
    

    要获取最后8位数字,我们可以使用

    sub('.*(\\d{8}).*', '\\1', my_text)
    #[1] "10293847"
    

    而对于第一个,我们可以使用

    sub('.*?(\\d{8}).*', '\\1', my_text)
    #[1] "12345654"
    

    编辑

    对于我们想要精确匹配 8 位(而不是更多)的更新案例,我们可以使用 str_match_all 并在后面进行否定查找

    stringr::str_match_all(my_text, "(?<!\\d)\\d{8}(?!\\d)")[[1]][, 1]
    #[1] "12345654" "99119911" "12345678" "10293847"
    

    在这里,我们得到 8 位数字,后面没有数字。

    一个简单的选项也可以是从字符串中提取所有数字并仅保留 8 位数字

    v1 <- regmatches(my_text, gregexpr("\\d+", my_text))[[1]]
    v1[nchar(v1) == 8]
    

    【讨论】:

    • 这可行,但有没有办法避免 stringr?我可以使用 sub 或 gsub 吗?
    • 我有一个非常大的表(大约 2 亿行),我需要对它的一列进行操作。是否有有效的矢量化解决方案?或者更确切地说,最有效的解决方案是什么?谢谢。
    • @Ankhnesmerira 我添加了一些选项。但不确定哪个是最有效的选择。
    • 我意识到我的文本案例中缺少案例。文本中还有一些数字长度超过 8 位,但我只想提取正好是 8 位的数字。
    • @Ankhnesmerira 好吧..我已根据您的更新更新了答案。
    【解决方案2】:

    我们可以更具体地这样做以避免任何极端情况

    library(stringr)
    str_extract_all(my_text, "(?<![0-9])[0-9]{8}(?![0-9])")[[1]]
    #[1] "12345654" "99119911" "12345678" "10293847"
    

    检查差异

    v1 <- "hello8888882343, 888884399, 88888888, 8888888888"
    str_extract_all(v1, "\\d{8}")
    #[[1]]
    #[1] "88888823" "88888439" "88888888" "88888888"
    

    在这里,它提取大于8的连续数字的子字符串。根据OP的帖子,它必须留下

    str_extract_all(v1,  "(?<![0-9])[0-9]{8}(?![0-9])")
    #[[1]]
    #[1] "88888888"
    

    【讨论】:

      猜你喜欢
      • 2021-11-09
      • 2021-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多