Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

haskell regex substitution

Despite the ridiculously large number of regex matching engines for Haskell, the only one I can find that will substitute is Text.Regex, which, while decent, is missing a few thing I like from pcre. Are there any pcre-based packages which will do substitution, or am I stuck with this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I don't think "just roll your own" is a reasonable answer to people trying to get actual work done, in an area where every other modern language has a trivial way to do this. Including Scheme. So here's some actual resources; my code is from a project where I was trying to replace "qql foo bar baz qq" with text based on calling a function on the stuff inside the qq "brackets", because reasons.

Best option: pcre-heavy:

      let newBody = gsub [re|s(qq[a-z]+)s(.*?)sqqs|] (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

Note that pcre-heavy directly supports function-based replacement, with any string type. So nice.

Another option: pcre-light with a small function that works but isn't exactly 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)

Someone else's fix: http://0xfe.blogspot.com/2010/09/regex-substitution-in-haskell.html

Another one, this time embedded in a major library: https://github.com/jaspervdj/hakyll/blob/master/src/Hakyll/Core/Util/String.hs

Another package for this purpose: https://hackage.haskell.org/package/pcre-utils


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...