Регулятор соответствия регулярному выражению Ruby с поддержкой названного захвата

Рассмотрим такую ​​строку, чтобы извлечь информацию о времени:

str = "Sun rises at 6:23 am & sets at 5:45 pm; Moon comes up by 7:20 pm and goes down by 3:45 am"

Я хочу иметь счетчик, например scan, но тот, который может получить мне MatchData​​strong > объекты, а не массивы, доступные из сканирования.

Например, я могу написать:

str.scan( /(?<time>\d:\d{2}) (?<meridiem>am|pm)/ ){ |arr| p arr }

чтобы получить:

["6:23", "am"] ["5:45", "pm"] ["7:20", "pm"] ["3:45", "am"]

Но, интересно, есть ли что-то вроде этого:

str.match_all( /(?<time>\d:\d{2}) (?<meridiem>am|pm)/ ){ |md| p md }

чтобы получить:

#<MatchData "6:23 am" time:"6:23" meridiem:"am"> #<MatchData "5:45 pm" time:"5:45" meridiem:"pm"> #<MatchData "7:20 pm" time:"7:20" meridiem:"pm"> #<MatchData "3:45 am" time:"3:45" meridiem:"am">

Увидел ответ в предыдущем вопросе, но я считаю его неэлегантным решением. Таким образом, проверка на случай, если что-то изменилось за последние пару лет с момента отправки ответа.

Ответ 1

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

str = "Sun rises at 6:23 am & sets at 5:45 pm; Moon comes up by 7:20 pm ..."
str.gsub(/(?<time>\d:\d{2}) (?<meridiem>am|pm)/).map{ Regexp.last_match } 

#=> [#<MatchData "6:23 am" time:"6:23" meridiem:"am">, #<MatchData "5:45 pm" ...