Регулярное выражение Haskell ведет себя по-другому:

#regex #haskell

#регулярное выражение #haskell

Вопрос:

Допустим, у меня есть следующее регулярное выражение для проверки того, что даты имеют формат ‘ГГГГ-ММ-ДД’:

([12]d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]d|3[01]))

Использование любого количества онлайн-тестеров регулярных выражений. (Мне нравится https://regex101.com /), становится очевидным, что это работает (например: 2055-12-12 выполняет синтаксический анализ правильно, 2055-13-25 не выполняет синтаксический анализ.

Теперь в haskell:

   import Text.Regex.TDFA
  import Text.Regex.TDFA.Text ()
  let dateRegex = "([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))" :: Text
  let fromDate' = "2055-12-12"
  putStrLn((fromDate' =~ dateRegex)::Text)
  

выдает пустую строку — не удается найти соответствие. Я понятия не имею, почему. Буду признателен за любую помощь.

Комментарии:

1. Это регулярные выражения в стиле perl (в частности d ), которые не поддерживаются (это написано в документации пакета regex-tdfa). Не уверен, например. {3} либо. В документах предлагается regex-pcre, или вы можете использовать выражения в стиле posix, например. [[:digit:]] .

2. @moonGoose Пожалуйста, напишите ответ, когда у вас будет время.

Ответ №1:

d значение цифры является особенностью регулярных выражений в стиле perl. В документах для regex-tdfa указано, что оно реализует posix extended, а не в стиле perl. Поэтому ваш выбор — переписать с использованием символьных классов posix, ie. использование [[:digit:]] ,

dateRegex = "([12][[:digit:]]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][[:digit:]]|3[01]))"

или вместо этого import "regex-pcre" Text.Regex.PCRE с вашим оригинальным регулярным выражением.

Ответ №2:

В Haskell обычный совет — анализировать, не проверять.

 import Text.Megaparsec
import Text.Megaparsec.Char
import Data.Time.Calendar
import Control.Monad
import Control.Monad.Fail
import Text.Read
import Data.Maybe
import Data.Void

parseDay :: Parsec Void String Day
parseDay = do
  y <- maybe (fail "bad year") pure =<< readMaybe <$> replicateM 4 digitChar
  chunk "-"
  m <- maybe (fail "bad month") pure =<< readMaybe <$> replicateM 2 digitChar
  chunk "-"
  d <- maybe (fail "bad day") pure =<< readMaybe <$> replicateM 2 digitChar
  maybe (fail "not a Gregorian calendar day") pure $ fromGregorianValid y m d
 
runParser parseDay "" "2020-11-30"
  
 Right 2020-11-30