【问题标题】:How do I find the last set of digits in a string如何找到字符串中的最后一组数字
【发布时间】:2022-01-04 10:03:47
【问题描述】:

假设我有一个字符串

"Happy 2022 New 01 years!"

我希望返回“01”。 更具体地说,我需要字符串中的最后一组数字。这个数字可能只是“1”、“10”或“999”…… 否则字符串几乎可以是任何东西。 我用 gsub 尝试了各种正则表达式,但似乎无法做到恰到好处。有一点我误会了。

例如,如果我这样做:

gsub('.*(\\d+).*$', '\\1', x)

那为什么我会返回“1”?正则表达式中的“+”是否未指定一位或多位数字?

我的解释怎么错了?: '.' 表示任何字符,'(\\d+)' 表示一位或多位数字,'.' 表示更多字符,'$' 在字符串的末尾。 gsub 是贪心的,所以它会返回最后一组数字(因此是 '01',而不是 '2022')。 '\\1' 将用第一个也是唯一的匹配替换整个字符串。 x 是字符串。

【问题讨论】:

  • stringi::stri_extract_last_regex(x, '\\d+')

标签: r regex regex-greedy


【解决方案1】:

在您的正则表达式中,.* 将匹配所有字符(换行符除外),从而匹配整个字符串。然后,引擎尝试匹配\d+,但字符串中没有更多字符可匹配。因此,回溯发生在.* 中,直到找到一个数字。一旦找到一个数字(即在您的情况下为 1),\d+ 匹配该数字,字符串的其余部分再次与 .* 匹配。

你可以试试这个正则表达式:

\d+(?![^\r\n\d]*\d)

Click for Demo

说明:

  • \d+ - 匹配 1 个或多个数字,尽可能多
  • (?![^\r\n\d]*\d) - 负前瞻以确保字符串后面没有更多数字

【讨论】:

  • 感谢您的解决方案和对该解决方案的良好解释!我想我现在明白了。我本来希望 \d+ 在回溯中也能匹配一个以上的数字。在这种情况下,\d 和 \d+ 之间真的没有区别吗?
  • @RobbeVankets 是的。在您的正则表达式中,如果您使用 \d 而不是 \d+,结果将是相同的。
  • 所以,这个 REGEX 在 DEMO 中起到了作用,但是当尝试在 R 中实现它时,我得到“TRE 模式编译错误 'Invalid regexp''”。任何想法为什么? (ofc 我首先添加了所需的第二个转义字符。)
  • @RobbeVankets 不是R 的专家,但我认为您需要设置perl=TRUE,如here 所述。 Here 是在正则表达式中稍作调整的工作代码
【解决方案2】:

在目标最终数字周围放置单词边界:

x <- "Happy 2022 New 01 years!"
num <- gsub('.*\\b(\\d+)\\b.*$', '\\1', x)
num

[1] "01"

这里的挑战是我们很想使用一个惰性点来停止第一个数字,例如.*?(\\d+).*。但问题是现在我们将停在第一个数字上,尽管我们想要最后一个。因此,贪心点是合适的,单词边界强制正则表达式捕获整个最终数字。

【讨论】:

  • 啊哈,谢谢你的建议。但是,这仅在空格围绕最终数字时才有效。我不能保证,所以我正在寻找更具防御性的替代方案。
  • @RobbeVankets 然后使用gsub('.*(?&lt;=\\D)(\\d+).*$', '\\1', x, perl=TRUE) ...我已经回答了您实际提出的问题。
【解决方案3】:

这可以工作:

(\d+)[^\d]*$

https://regex101.com/r/DHrttA/1

在你的解决方案中,我认为问题在于第一个 .* 是贪婪的,所以它会跳过它所能做的。

【讨论】:

  • 没有,抱歉。这将返回“01 年!”
  • @RobbeVankets 不,这是完全匹配。您必须与第一组合作。
【解决方案4】:

使用strsplit的解决方法

> tail(strsplit(x, "\\D+")[[1]], 1)
[1] "01"

【讨论】:

  • 确实有效!但是,对于这种特殊情况,我更喜欢使用 gsub。不过谢谢你的回复。
  • @RobbeVankets 别担心,我只是想为您提供更多可能的不同想法的选择
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-13
  • 2014-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多