Replace regex match by arbitrary function of match itself

Viewed 83

I'm trying to write a function of type Text -> (Text -> Text) -> Text that replaces occurrences of a regular expression in a piece of text by something else that is a function of what the regular expression has matched. There is subRegex from Text.Regex but this only allows replacing a match with some fixed replacement string whereas I would like the replacement to an an arbitrary function of the match. Is there a package that already implements something like that?

2 Answers

You can use matchRegexAll

matchRegexAll
   :: Regex     -- ^ The regular expression
   -> String    -- ^ The string to match against
   -> Maybe ( String, String, String, [String] )
                -- ^ Returns: 'Nothing' if the match failed, or:
                --
                -- >  Just ( everything before match,
                -- >         portion matched,
                -- >         everything after the match,
                -- >         subexpression matches )

For example:

subFirst :: Regex -> String -> (String -> String) -> String
subFirst rx input f = case matchRegexAll rx input of
    Nothing -> input
    Just (pre, match, post, _) -> pre <> f match <> post

If you want to do this for all matches rather than just the first, you can call this function recursively on the remainder post (left as an exercise).

For a different approach, it looks like the text-regex-replace replace package might be of use to you. It works directly on Text rather than String, and it appears to have the capability of arbitrary replacement functions (however the usage seems a bit obtuse).

Related