正则表达式:从多个匹配的括号中提取数字

时间:2017-10-18 19:45:35

标签: r regex pattern-matching parentheses

我如何匹配年份,以便它适用于以下示例。

a <- '"You Are There" (1953) {The Death of Socrates (399 B.C.) (#1.14)}'
b <- 'Þegar það gerist (1998/I) (TV)'

我尝试了以下方法,但没有取得最大的成功。

gsub('.+\\(([0-9]+.+\\)).?$', '\\1', a)

我认为它的作用是直到它找到一个(然后它会产生一组数字,然后是任何角色,直到它遇到a)。如果有几个匹配,我想提取第一组。

对我出错的地方有什么建议吗?我一直在做这个。

2 个答案:

答案 0 :(得分:2)

您可以使用

library(stringr)

strings <- c('"You Are There" (1953) {The Death of Socrates (399 B.C.) (#1.14)}', 'Þegar það gerist (1998/I) (TV)')

years <- str_match(strings, "\\((\\d+(?: B\\.C\\.)?)")[,2]
years
# [1] "1953" "1998"

这里的表达是

\(               # (
(\d+             # capture 1+ digits
    (?: B\.C\.)? # B.C. eventually
)

请注意,需要在R转义反斜杠。

答案 1 :(得分:1)

您的模式包含尽可能多的匹配1个或多个字符的.+个部分,最多您的模式可以从传入的字符串中获取最后4个数字的块。

您可以使用

^.*?\((\d{4})(?:/[^)]*)?\).*

替换为\1仅保留4位数字。请参阅the regex demo

<强>详情

  • ^ - 字符串开头
  • .*? - 尽可能少的0个字符
  • \( - (
  • (\d{4}) - 第1组:四位数
  • (?: - 启动可选的非捕获组
    • / - /
    • [^)]* - 除)
    • 以外的任何0 +字符
  • )? - 小组结尾
  • \) - )(可选,可以省略)
  • .* - 字符串的其余部分。

请参阅R demo

a <- c('"You Are There" (1953) {The Death of Socrates (399 B.C.) (#1.14)}', 'Þegar það gerist (1998/I) (TV)', 'Johannes Passion, BWV. 245 (1725 Version) (1996) (V)')
sub("^.*?\\((\\d{4})(?:/[^)]*)?\\).*", "\\1", a) 
# => [1] "1953" "1998" "1996"

另一个基本R解决方案是匹配(之后的4位数:

regmatches(a, regexpr("\\(\\K\\d{4}(?=(?:/[^)]*)?\\))", a, perl=TRUE))
# => [1] "1953" "1998" "1996"

\(\K\d{4}模式与(匹配,然后由于\K匹配重置运算符而丢弃它,然后(?=(?:/[^)]*)?\\))前瞻确保存在可选的/ +除)以外的0 +字符,然后是)。请注意,regexpr仅提取第一个匹配项。