Как написать оператор переключения Ruby (case ... when) с регулярными выражениями и обратными ссылками? - PullRequest
77 голосов
/ 24 июля 2011

Я знаю, что могу написать оператор в Ruby, чтобы проверить соответствие регулярным выражениям. Тем не менее, я хотел бы использовать данные о совпадении в моем операторе возврата. Примерно такой полупсевдокод:

foo = "10/10/2011"

case foo
    when /^([0-9][0-9])/
        print "the month is #{match[1]}"
    else
        print "something else"
end

Как мне этого добиться?

Спасибо!


Просто примечание: я понимаю, что никогда не буду использовать оператор switch для простого случая, как указано выше, но это только один пример. На самом деле я пытаюсь достичь соответствия многих потенциальных регулярных выражений для даты, которые можно записать различными способами, и затем соответствующим образом проанализировать ее с помощью класса Date в Ruby.

Ответы [ 2 ]

143 голосов
/ 24 июля 2011

Ссылки на последние группы соответствия регулярному выражению всегда хранятся в псевдопеременных $1 до $9:

case foo
when /^([0-9][0-9])/
    print "the month is #{$1}"
else
    print "something else"
end

Вы также можете использовать псевдопеременную $LAST_MATCH_INFO для получения всего объекта MatchData. Это может быть полезно при использовании именованных захватов:

case foo
when /^(?<number>[0-9][0-9])/
    print "the month is #{$LAST_MATCH_INFO['number']}"
else
    print "something else"
end
6 голосов
/ 24 июля 2011

Вот альтернативный подход, который дает вам тот же результат, но не использует переключатель. Если вы поместите ваши регулярные выражения в массив, вы можете сделать что-то вроде этого:

res = [ /pat1/, /pat2/, ... ]
m   = nil
res.find { |re| m = foo.match(re) }
# Do what you will with `m` now.

Объявление m вне блока позволяет ему оставаться доступным после того, как find выполнено с блоком и find остановится, как только блок вернет истинное значение, поэтому вы получаете такое же быстрое поведение, что и переключатель. Это дает вам полный MatchData, если вам это нужно (возможно, вы хотите использовать именованные группы захвата в своих регулярных выражениях) и приятно отделяет ваши регулярные выражения от логики поиска (что может давать или не давать более четкий код) Вы можете даже загрузить свои регулярные выражения из конфигурационного файла или выбрать, какой набор из них вы хотите во время выполнения.

...