PCRE в Haskell - что, где, как?
Я искал некоторую документацию или учебник по регулярным выражениям Haskell на века. Нет никакой полезной информации на странице HaskellWiki. Он просто дает загадочное сообщение:
Documentation
Coming soonish.
Есть короткий пост в блоге, который я нашел довольно полезным, однако он касается только регулярных выражений Posix, а не PCRE.
Я работаю с регулярным выражением Posix в течение нескольких недель, и я прихожу к выводу, что для моей задачи мне нужен PCRE.
Моя проблема в том, что я не знаю, с чего начать с PCRE в Haskell. Я загрузил regex-pcre-builtin
с помощью cabal, но мне нужен пример простой программы соответствия, чтобы помочь мне начать работу.
- Возможно ли реализовать многострочное сопоставление?
- Могу ли я получить спички в этом формате:
[(MatchOffset,MatchLength)]
?
- Какие еще форматы я могу получить в матчах?
Большое спасибо за любую помощь!
Ответы
Ответ 1
Хорошо, я написал большую часть вики-страницы и, возможно, написал "Coming soonish". Пакет regex-pcre представлял собой мою упаковку PCRE с использованием интерфейса regex-base, где regex-base используется как интерфейс для нескольких очень разных баз данных механизма регулярных выражений. У пакета Doncewart pcre-light нет этого слоя абстракции и, следовательно, намного меньше.
Сообщение в блоге Text.Regex.Posix использует мой пакет regex-posix, который также находится поверх базы regex. Таким образом, использование regex-pcre будет очень похоже на это сообщение в блоге, за исключением того, что параметры компиляции и выполнения PCRE различаются.
Для настройки regex-pcre Модуль Text.Regex.PCRE.Wrap имеет необходимые вам константы. Используйте makeRegexOptsM из regex-base, чтобы указать параметры.
Ответ 2
Есть два основных параметра, когда вы хотите использовать регулярные выражения типа PCRE в Haskell:
-
regex-pcre использует тот же интерфейс, который описан в этом сообщении в блоге (а также в RWH, как я думаю, расширенная версия этого блога); это может быть дополнительно расширено pcre-less. regex-pcre-builtin, кажется, является предварительным выпуском этого снимка и, вероятно, не должен использоваться.
-
pcre-light - привязки к библиотеке PCRE. Он не предоставляет типы возвращаемых результатов, а только все сопоставления (если есть). Тем не менее, пакет pcre-light-extras предоставляет класс MatchResult
, для которого вы могли бы предоставить такой экземпляр. Это можно улучшить, используя regexqq, который позволяет использовать квазицитирование, чтобы гарантировать, что ваш тип шаблона регулярного выражения; однако он не работает с GHC-7 (и если кто-то не возьмет его на себя, он не будет).
Итак, если вы идете с regex-pcre
:
-
В соответствии с ответом this да.
-
Я так думаю, используя тип MatchArray
(он возвращает массив, из которого вы можете получить список).
-
Смотрите здесь для всех возможных результатов из регулярного выражения.
Ответ 3
Там также regex-applicative, который я написал.
Идея состоит в том, что вы можете назначить некоторый смысл каждой части регулярного выражения, а затем составить их, точно так же, как вы пишете парсеры с использованием Parsec.
Вот пример - простой синтаксический анализ URL.
import Text.Regex.Applicative
data Protocol = HTTP | FTP deriving Show
protocol :: RE Char Protocol
protocol = HTTP <$ string "http" <|> FTP <$ string "ftp"
type Host = String
type Location = String
data URL = URL Protocol Host Location deriving Show
host :: RE Char Host
host = many $ psym $ (/= '/')
url :: RE Char URL
url = URL <$> protocol <* string "://" <*> host <* sym '/' <*> many anySym
main = print $ "http://stackoverflow.com/questions" =~ url
Ответ 4
regexpr - это еще один PCRE-ish lib, который кросс-платформенный и быстрый для начала.
Ответ 5
Я нахожу rex, что тоже очень приятно, его интеграция с ViewPatterns - хорошая идея, я думаю.
Он может быть многословным, но частично связанным с понятием регулярного выражения.
parseDate :: String -> LocalTime
parseDate [rex|(?{read -> year}\d+)-(?{read -> month}\d+)-
(?{read -> day}\d+)\s(?{read -> hour}\d+):(?{read -> mins}\d+):
(?{read -> sec}\d+)|] =
LocalTime (fromGregorian year month day) (TimeOfDay hour mins sec)
parseDate [email protected]_ = error $ "invalid date " ++ v
Это говорит о том, что я только что обнаружил применение регулярных выражений, упомянутое в одном из других ответов, и это может быть лучший выбор, может быть менее подробным и более идиоматичным, хотя rex имеет в основном нулевую кривую обучения, если вы знаете регулярные выражения, которые могут быть плюс.