2010-10-02 35 views
21

A pesar de la ridícula gran número de expresiones regulares juego motores para Haskell, el único que puede encontrar que se sustituto es Text.Regex, que, aunque decente, no se encuentra unos pocos cosa que me gusta de pcre. ¿Hay paquetes basados ​​en pcre que harán la sustitución, o estoy atascado con esto?Haskell sustitución de expresiones regulares

+2

Buena pregunta, me he encontrado con el mismo problema. –

+2

bien, atornilla eso, escribí el mío basado en 'Text.Regex.PCRE.Light', aunque se adapta muy bien a la mayoría de las otras implementaciones. – muhmuhten

+5

Publique eso como respuesta si resuelve el problema. – kennytm

Respuesta

3

La API de expresión regular en regex-base es genérica para el contenedor de caracteres que coinciden. Hacer algún tipo de empalme genérico para implementar la sustitución sería muy difícil de hacer eficiente. No quería proporcionar una rutina genérica horrible.

Escribir una función pequeña para hacer la sustitución exactamente como lo desee es simplemente una mejor idea, y se puede escribir para que coincida con su contenedor.

4

No creo que "solo enrollar el suyo" sea una respuesta razonable para las personas que intentan realizar un trabajo real, en un área donde cualquier otro idioma moderno tiene una forma trivial de hacerlo. Incluyendo Scheme. Así que aquí hay algunos recursos reales; mi código es de un proyecto en el que estaba tratando de reemplazar "qql foo bar baz qq" con texto basado en llamar a una función en el material dentro de los "corchetes" qq, porque hay razones.

La mejor opción: pcre-pesado:

 let newBody = gsub [re|\s(qq[a-z]+)\s(.*?)\sqq\s|] (unWikiReplacer2 titles) body in do 
[snip] 
unWikiReplacer2 :: [String] -> String -> [String] -> String 
unWikiReplacer2 titles match subList = case length subList > 0 of 
     True -> " --" ++ subList!!1 ++ "-- " 
     False -> match 

Tenga en cuenta que pcre-pesada directamente apoya reemplazo basado en la función, con cualquier tipo cadena. Tan agradable.

Otra opción: pcre-luz con una pequeña función que funciona, pero no es exactamente performant:

let newBody = replaceAllPCRE "\\s(qq[a-z]+)\\s(.*?)\\sqq\\s" (unWikiReplacer titles) body in do 
[snip] 
unWikiReplacer :: [String] -> (PCRE.MatchResult String) -> String 
unWikiReplacer titles mr = case length subList > 0 of 
     True -> " --" ++ subList!!1 ++ "-- " 
     False -> PCRE.mrMatch mr 
    where 
     subList = PCRE.mrSubList mr 

-- A very simple, very dumb "replace all instances of this regex 
-- with the results of this function" function. Relies on the 
-- MatchResult return type. 
-- 
-- https://github.com/erantapaa/haskell-regexp-examples/blob/master/RegexExamples.hs 
-- was very helpful to me in constructing this 
-- 
-- I also used 
-- https://github.com/jaspervdj/hakyll/blob/ea7d97498275a23fbda06e168904ee261f29594e/src/Hakyll/Core/Util/String.hs 
replaceAllPCRE :: String    --^Pattern 
      -> ((PCRE.MatchResult String) -> String) --^Replacement (called on capture) 
      -> String    --^Source string 
      -> String    --^Result 
replaceAllPCRE pattern f source = 
    if (source PCRE.=~ pattern) == True then 
     replaceAllPCRE pattern f newStr 
    else 
     source 
    where 
     mr = (source PCRE.=~ pattern) 
     newStr = (PCRE.mrBefore mr) ++ (f mr) ++ (PCRE.mrAfter mr) 

de alguien más solución: http://0xfe.blogspot.com/2010/09/regex-substitution-in-haskell.html

Otro, esta vez incrustado en una biblioteca importante : https://github.com/jaspervdj/hakyll/blob/master/src/Hakyll/Core/Util/String.hs

Otro paquete para este propósito: https://hackage.haskell.org/package/pcre-utils

Cuestiones relacionadas