2010-10-02 5 views
21

Malgré le nombre ridiculement élevé de regex moteurs correspondant pour Haskell, le seul, je peux constater que va substitut est Text.Regex, qui, bien que décent, manque quelques chose que j'aime de PCRE. Y a-t-il des paquets basés sur pcre qui vont faire la substitution, ou suis-je coincé avec ceci?haskell de substitution regex

+2

Bonne question, j'ai rencontré le même problème. –

+2

okay, vis cela, j'ai écrit le mien basé sur 'Text.Regex.PCRE.Light', bien qu'il ports joliment à la plupart des autres implémentations. – muhmuhten

+5

Publiez cette réponse si elle résout le problème. – kennytm

Répondre

3

L'API d'expression régulière dans regex-base est générique pour le conteneur de caractères à faire correspondre. Faire une sorte d'épissage générique pour implémenter la substitution serait très difficile à rendre efficace. Je ne voulais pas fournir une routine générique merdique.

Écrire une petite fonction pour faire la substitution exactement comme vous voulez est juste une meilleure idée, et il peut être écrit pour correspondre à votre conteneur.

4

Je ne pense pas que "juste rouler le vôtre" est une réponse raisonnable aux personnes qui essaient de faire le travail réel, dans une zone où toutes les autres langues modernes a une manière triviale de le faire. Y compris schéma. Alors, voici quelques ressources réelles; mon code provient d'un projet où j'essayais de remplacer "qql foo bar baz qq" par du texte basé sur l'appel d'une fonction sur le contenu à l'intérieur des qq "parenthèses", pour des raisons.

La meilleure option: PCRE-lourds:

 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 

Notez que PCRE lourds directement prend en charge le remplacement par fonction, avec tout type de chaîne . Vraiment gentil.

Une autre option: PCRE-lumière avec une petite fonction qui fonctionne mais pas exactement 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 quelqu'un d'autre solution: http://0xfe.blogspot.com/2010/09/regex-substitution-in-haskell.html

Un autre, cette fois embarqué dans une grande bibliothèque : https://github.com/jaspervdj/hakyll/blob/master/src/Hakyll/Core/Util/String.hs

Un autre paquet à cet effet: https://hackage.haskell.org/package/pcre-utils