从字符串中提取年份的正则表达式

3
这应该很简单,但我似乎无法让它正常工作。其目的是从Mp3tag中的mp3文件名中提取v3标签。
我有这些字符串,想要提取年份。
Test String 1 (1994) -> extract 1994
34 Test String 2 (1995)" -> extract 1995
Test (String) 3 (1996)" -> extract 1996

我有一个正则表达式^(.+)\s\(([0-9]*)\)$,但显然它没有给我预期的结果。你可以说我对正则表达式不是很熟悉。谢谢提前帮助。
5个回答

21

以下是更通用的解决方案建议,不确定是否适用于您的情况。有效年份始终具有19xx或20xx格式,并且年份将使用断词字符(而非数字或字母)分隔:

\b(19|20)\d{2}\b

这个表达式并不关心年份在标签中的位置。一个更简单的版本,不假设年份有多于 4 个数字的表达式是:

\b\d{4}\b

关键在于使用 \b 转义字符,它匹配任何非单词字符(包括括号),单词字符是字母、数字和下划线。

我还想推荐这个网站: http://www.regular-expressions.info/


9
您可以使用类似于 \((\d{4})\)$ 的东西。第一组将拥有您的匹配。
解释:这是一个正则表达式,它匹配以四个数字结尾并在括号内的字符串,并将其中的四个数字作为第一组返回。
\(       # Match the character “(” literally
(        # Match the regular expression below and capture its match into backreference number 1
   \d       # Match a single digit 0..9
      {4}      # Exactly 4 times
)
\)       # Match the character “)” literally
$        # Assert position at the end of a line (at the end of the string or before a line break character)

2

您需要转义括号。此外,您可以限制一年只有4个数字:

^(.+)\s\(([0-9]{4})\)$

年份在匹配组2中。

糟糕,看起来我忘记添加转义了。嗯,好像Mp3tag没有识别它 :'(。 - nixgadget
为什么在不必要的情况下要将字符串的开头存储在组中? - johnsyweb
@Johnsyweb:你怎么不存储它? - cherouvim
我没有将它存储在我的答案中。 - johnsyweb

1

我会选择

^(.*)\s\(([0-9]{4})\)$

(假设所有年份都有4位数字,如果您不知道数字的位数但至少有一位,请使用[0-9]+,或者如果可能没有数字,请使用[0-9]*


为什么在不需要的情况下将字符串的开头存储在组中? - johnsyweb
因为这也是原始问题的内容。 - Martijn

1

你的正则表达式已经接近完成了。

你现在需要的是:

\s\((\d{4})\)$

说明:

  • \s 表示空格
  • \( 表示左括号
  • ( 表示匹配组的开始
  • \d 表示数字
  • {4} 表示前面的原子重复四次(即四个数字)
  • ) 表示匹配组的结束
  • \) 表示右括号
  • $ 表示字符串的结尾

为了获得最佳结果,请将其放入函数中:

>>> def get_year(name):
...     return re.search('\s\((\d{4})\)$', name).groups()[0]
... 
>>> for name in "Test String 1 (1994)", "34 Test String 2 (1995)", "Test (String) 3 (1996)":
...     print get_year(name)
... 
1994
1995
1996

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接