regex - PCRE en Haskell: ¿qué, dónde, cómo?
(5)
He estado buscando alguna documentación o un tutorial sobre expresiones regulares de Haskell durante años. No hay información útil en la página HaskellWiki . Simplemente da el mensaje críptico:
Documentation
Coming soonish.
Hay una breve publicación en el blog que he encontrado bastante útil, sin embargo, solo trata con expresiones regulares de Posix, no con PCRE.
He estado trabajando con Posix regex durante algunas semanas y llego a la conclusión de que para mi tarea necesito PCRE.
Mi problema es que no sé por dónde empezar con PCRE en Haskell. He descargado regex-pcre-builtin
con cabal pero necesito un ejemplo de un programa de coincidencia simple para ayudarme a seguir.
- ¿Es posible implementar la coincidencia multilínea?
- ¿Puedo recuperar las coincidencias en este formato:
[(MatchOffset,MatchLength)]
? - ¿En qué otros formatos puedo obtener las coincidencias?
¡Muchas gracias por cualquier ayuda!
Bueno, escribí gran parte de la página wiki y podría haber escrito "Próximamente". El paquete regex-pcre fue mi envoltorio de PCRE usando la interfaz regex-base, donde regex-base se usa como interfaz para varios motores de expresiones regulares muy diferentes. El paquete pcre-light de Don Stewart no tiene esta capa de abstracción y, por lo tanto, es mucho más pequeño.
La publicación del blog en Text.Regex.Posix usa mi paquete regex-posix que también se encuentra en la parte superior de regex-base. Por lo tanto, el uso de regex-pcre será muy similar al de la publicación del blog, excepto que las opciones de compilación y ejecución de PCRE son diferentes.
Para configurar regex-pcre, el módulo Text.Regex.PCRE.Wrap tiene las constantes que necesita. Use makeRegexOptsM de regex-base para especificar las opciones.
Hay dos opciones principales al querer usar expresiones regulares de estilo PCRE en Haskell:
regex-pcre usa la misma interfaz que se describe en esa publicación del blog (y también en RWH , ya que creo que una versión ampliada de esa publicación del blog); Esto se puede ampliar opcionalmente con pcre-less . regex-pcre-builtin parece ser una instantánea preliminar de esto y probablemente no debería utilizarse.
pcre-light es enlaces a la biblioteca PCRE. No proporciona los tipos de devolución que está buscando, solo todos los emparejamientos (si los hay). Sin embargo , el paquete pcre-light-extras proporciona una clase
MatchResult
, para la cual podría proporcionar dicha instancia. Esto se puede mejorar usando regexqq que le permite usar casi las cotizaciones para asegurarse de que su tipo de expresión regular verifique; sin embargo, no funciona con GHC-7 (y, a menos que alguien se encargue de mantenerlo, no lo hará).
Entonces, asumiendo que vas con regex-pcre
:
Me parece que rex es bastante bueno también, creo que su integración con ViewPatterns es una buena idea.
Sin embargo, puede ser detallado pero está parcialmente relacionado con el concepto de expresiones regulares.
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
Dicho esto, acabo de descubrir el uso de expresiones regulares mencionado en una de las otras respuestas y puede ser una mejor opción, podría ser menos detallado y más idiomático, aunque rex tiene una curva de aprendizaje prácticamente nula si conoce expresiones regulares que pueden ser una ventaja.
También hay regex-applicative que he escrito.
La idea es que puede asignar algún significado a cada parte de una expresión regular y luego redactarlas, al igual que escribe analizadores usando Parsec.
Aquí hay un ejemplo: un simple análisis de 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://.com/questions" =~ url