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

Regex: Extracting numbers from parentheses with multiple matches

如何匹配年份以使其对以下示例具有通用性。

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)

我认为它所做的是直到它找到一个 (,然后它会组成一组数字,然后是任何字符,直到它遇到一个 )。如果有几场比赛,我想提取第一组。

对我哪里出错有什么建议吗?我一直在 R 中这样做。

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

您可以使用

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

替换为 </code> 以仅保留 4 位数字。参见 <a href="https://regex101.com/r/hn6OW2/3" rel="nofollow noreferrer">the regex demo</a>。</p> <p><strong>详情</strong></p> <ul> <li><code>^ - 字符串开头

  • .*? - 任何 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"
    

    另一种base R方案是匹配(后的4位:

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

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

    你可以使用

    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中的反斜杠需要转义。