PCRE в Haskell - что, где, как? - PullRequest
       52

PCRE в Haskell - что, где, как?

17 голосов
/ 25 октября 2011

Я давно искал документацию или учебник по регулярным выражениям на Haskell.На странице HaskellWiki нет полезной информации.Он просто дает загадочное сообщение:

Documentation
Coming soonish.

Существует краткое сообщение в блоге , которое я считаю довольно полезным, однако оно касается только регулярных выражений Posix, а не PCRE.

Я работаю с Posix regex в течение нескольких недель и прихожу к выводу, что для моей задачи мне нужен PCRE.

Моя проблема в том, что я не знаю, с чего начатьPCRE в Хаскеле.Я скачал regex-pcre-builtin с помощью cabal, но мне нужен пример простой программы сопоставления , чтобы помочь мне начать работу.

  • Можно ли реализовать многострочное сопоставление?
  • Могу ли я вернуть совпадения в следующем формате: [(MatchOffset,MatchLength)]?
  • В каких других форматах я могу вернуть совпадения?

Большое спасибоза любую помощь!

Ответы [ 5 ]

10 голосов
/ 26 октября 2011

Есть также регулярное выражение , которое я написал.

Идея состоит в том, что вы можете присвоить некоторый смысл каждому фрагменту регулярного выражения, а затем составить их так же, как вы пишете парсеры с использованием 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
10 голосов
/ 25 октября 2011

Существует два основных варианта использования регулярных выражений в стиле PCRE в Haskell:

  • regex-pcre использует тот же интерфейс, который описан в этом сообщении в блоге (а также в RWH , как я думаю, расширенную версию этого сообщения в блоге); это может быть дополнительно расширено pcre-less . regex-pcre-builtin , кажется, является предварительным снимком этого релиза и, вероятно, не должен использоваться.

  • pcre-light - это привязки к библиотеке PCRE. Он не предоставляет типы возвращаемых данных, которые вам нужны, только все совпадения (если есть). Однако , пакет pcre-light-extras предоставляет класс MatchResult, для которого вы могли бы предоставить такой экземпляр. Это может быть улучшено с помощью regexqq , что позволяет вам использовать квази-кавычки, чтобы гарантировать, что ваш шаблон регулярных выражений проверяет тип; однако, он не работает с GHC-7 (и если кто-то не возьмет его на себя, он не будет).

Итак, предполагая, что вы идете с regex-pcre:

  • Согласно этому ответу, да.

  • Я так думаю, через тип MatchArray (он возвращает массив, из которого вы затем можете получить список).

  • См. здесь для всех возможных результатов регулярного выражения.

5 голосов
/ 25 октября 2011

Что ж, я написал большую часть вики-страницы и, возможно, написал «Скоро будет». Пакет regex-pcre был моей оболочкой PCRE с использованием интерфейса regex-base, где regex-base используется в качестве интерфейса для нескольких совершенно разных бэкэндов движка регулярных выражений. Пакет pcre-light от Don Stewart не имеет этого слоя абстракции и поэтому намного меньше.

В блоге Text.Regex.Posix используется мой пакет regex-posix, который также находится над базой regex-base. Таким образом, использование regex-pcre будет очень похоже на это сообщение в блоге, за исключением того, что параметры компиляции и выполнения PCRE отличаются.

Для настройки regex-pcre модуль Text.Regex.PCRE.Wrap содержит необходимые вам константы. Используйте makeRegexOptsM из regex-base, чтобы указать параметры.

5 голосов
/ 25 октября 2011

regexpr - еще одна библиотека PCRE-ish, кроссплатформенная и с которой можно быстро начать работу.

2 голосов
/ 14 февраля 2014

Я нахожу, что 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 v@_ = error $ "invalid date " ++ v

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

...