如何匹配正则表达式中的不同组
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+)
年份匹配捕获
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*
之后。)
我有以下字符串:
"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+)
年份匹配捕获
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*
之后。)