如何匹配正则表达式中的不同组

How to match different groups in regex

我有以下字符串:

"Josua de Grave* (1643-1712)"

*之前的都是人名,第一个日期1634是他的生日,1712是他的逝世日期。

按照这个逻辑,我想为每个项目设置 3 个匹配组。我试过了

([a-zA-Z|\s]*)\* (\d{3,4})-(\d{3,4})
"Josua de Grave* (1643-1712)".match(/([a-zA-Z|\s]*)\* (\d{3,4})-(\d{3,4})/)

但是 returns 没有。

为什么我的逻辑错了,我应该怎么做才能得到3个预期的匹配组。

数字 1643-1712 值周围的附加括号 ( ) 需要添加到您的正则表达式模式中,因此请使用

([a-zA-Z\s]*)\* \((\d{3,4})-(\d{3,4})\)
//               ^^                   ^^

由于方括号代表捕获的组,因此使用 \ 将它们转义以将它们作为字符匹配。

虽然您可以使用模式,但使用其他Ruby方法也可以轻松解决将其拆分成多个部分的问题:

使用 split:

s = "Josua de Grave* (1643-1712)"
name, dates = s.split('*') # => ["Josua de Grave", " (1643-1712)"]
birth, death = dates[2..-2].split('-') # => ["1643", "1712"]

或者,使用 scan:

*name, birth, death = s.scan(/[[:alnum:]]+/) # => ["Josua", "de", "Grave", "1643", "1712"]
name.join(' ')  # => "Josua de Grave"
birth # => "1643"
death # => "1712"

如果我使用模式,我会使用这个:

name, birth, death = /^([^*]+).+?(\d+)-(\d+)/.match(s)[1..3] # => ["Josua de Grave", "1643", "1712"]
name # => "Josua de Grave"
birth # => "1643"
death # => "1712"

/(^[^*]+).+?(\d+)-(\d+)/ 表示:

  • ^ 从缓冲区的开头开始
  • ([^*]+) 捕获所有内容 而不是 *,它将停止捕获
  • .+? 跳过最小值直到...
  • (\d+)年份匹配捕获
  • - 匹配但不捕获
  • (\d+)年份匹配捕获

Regexper helps explain it as does Rubular.

r = /\*\s+\(|(?<=\d)\s*-\s*|\)/

"Josua de Grave* (1643-1712)".split r
  #=> ["Josua de Grave", "1643", "1712"] 

"Sir Winston Leonard Spencer-Churchill* (1874 - 1965)".split r
  #=> ["Sir Winston Leonard Spencer-Churchill", "1874", "1965"]

通过在自由间距模式下编写正则表达式可以使其成为自文档:

r = /
    \*\s+\(  # match '*' then >= 1 whitespaces then '('
    |        # or
    (?<=\d)  # match is preceded by a digit (positive lookbehind)
    \s*-\s*  # match >= 0 whitespaces then '-' then >= 0 whitespaces 
    |        # or
    \)       # match ')'
    /x       # free-spacing regex definition mode

需要 正向回顾 以避免在连字符上拆分带连字符的名称。 (可以使用 positive lookahead (?=\d),放在 \s*-\s* 之后。)