Как сопоставить разные группы в регулярных выражениях - PullRequest
2 голосов
/ 15 февраля 2020

У меня есть следующая строка:

"Josua de Grave* (1643-1712)"

Все до * - это имя человека, первая дата 1634 - это дата его рождения, 1712 - это дата его смерти.

Следуя этой логике c Я хотел бы иметь 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})/)

, но это возвращает ноль.

Почему мои логики c неверны, и что я должен сделать, чтобы получить 3 предполагаемые группы совпадений.

Ответы [ 3 ]

1 голос
/ 16 февраля 2020

Хотя вы можете использовать шаблон, проблему разбиения его на части можно легко решить с помощью других 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 помогает объяснить это так же, как Rubular .

1 голос
/ 16 февраля 2020
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

Требуется положительный вид сзади чтобы избежать разбиения имен переносов на дефисы. (Вместо этого можно использовать положительный прогноз (?=\d), расположенный после \s*-\s*.)

1 голос
/ 15 февраля 2020

Дополнительные скобки ( ) вокруг значений di git 1643-1712 необходимо добавить в шаблон регулярных выражений, поэтому используйте

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

, так как скобки представляют захваченную группу, поэтому избегайте их используя \ для сопоставления их как символа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...