Regex 用Haskell正则表达式库替换/替换

Regex 用Haskell正则表达式库替换/替换,regex,haskell,Regex,Haskell,在Haskell中是否有用于搜索并替换为正则表达式的高级API?我特别关注Text.Regex.TDFA或Text.Regex.Posix包。我真的想要一种: f :: Regex -> (ResultInfo -> m String) -> String -> m String 例如,用“猫”代替“狗”,你可以写 runIdentity . f "dog" (return . const "cat") -- :: String -> String 或者用

在Haskell中是否有用于搜索并替换为正则表达式的高级API?我特别关注
Text.Regex.TDFA
Text.Regex.Posix
包。我真的想要一种:

f :: Regex -> (ResultInfo -> m String) -> String -> m String
例如,用“猫”代替“狗”,你可以写

runIdentity . f "dog" (return . const "cat")    -- :: String -> String
或者用monad做更高级的事情,比如计算事件发生次数等


这方面的Haskell文档非常缺乏。一些低级API注释是。

我不知道有任何现有函数可以创建此功能,但我认为我最终会使用类似的东西来模拟它:

replaceAll :: RegexLike r String => r -> (String -> String) -> String -> String
replaceAll re f s = start end
  where (_, end, start) = foldl' go (0, s, id) $ getAllMatches $ match re s
        go (ind,read,write) (off,len) =
          let (skip, start) = splitAt (off - ind) read 
              (matched, remaining) = splitAt len matched 
          in (off + len, remaining, write . (skip++) . (f matched ++))

replaceAllM :: (Monad m, RegexLike r String) => r -> (String -> m String) -> String -> m String
replaceAllM re f s = do
  let go (ind,read,write) (off,len) = do
      let (skip, start) = splitAt (off - ind) read 
      let (matched, remaining) = splitAt len matched 
      replacement <- f matched
      return (off + len, remaining, write . (skip++) . (replacement++))
  (_, end, start) <- foldM go (0, s, return) $ getAllMatches $ match re s
  start end
replaceAll::RegexLike r String=>r->(String->String)->String->String
replaceAll re f s=开始-结束
其中(u,end,start)=foldl'go(0,s,id)$getAllMatches$match re s
去(读,写)(关,兰)=
let(skip,start)=splitAt(off-ind)read
(匹配,剩余)=在len匹配时拆分
在(off+len,剩余,写入)中。(跳过++)(f匹配++)
replaceAllM::(Monad m,RegexLike r String)=>r->(String->m String)->String->m String
replaceAllM re f s=do
放手,放手
let(skip,start)=splitAt(off-ind)read
let(匹配,剩余)=在len匹配时拆分
更换包装内的
regex compat
如何

Prelude> import Text.Regex (mkRegex, subRegex)

Prelude> :t mkRegex
mkRegex :: String -> Regex

Prelude> :t subRegex
subRegex :: Regex -> String -> String -> String

Prelude> subRegex (mkRegex "foo") "foobar" "123"
"123bar"

也许这种方法适合你

import Data.Array (elems)
import Text.Regex.TDFA ((=~), MatchArray)

replaceAll :: String -> String -> String -> String        
replaceAll regex new_str str  = 
    let parts = concat $ map elems $ (str  =~  regex :: [MatchArray])
    in foldl (replace' new_str) str (reverse parts) 

  where
     replace' :: [a] -> [a] -> (Int, Int) -> [a]
     replace' new list (shift, l)   = 
        let (pre, post) = splitAt shift list
        in pre ++ new ++ (drop l post)

基于@rampion的答案,但由于排印错误已修复,因此它不仅仅是


您可以从中使用
replaceAll


我建议用“monad的更高级的东西,比如计数事件等”来进行“搜索和替换”

有关如何计数事件的具体示例,请参阅软件包自述

replaceAll :: Regex -> (String -> String) -> String -> String
replaceAll re f s = start end
  where (_, end, start) = foldl' go (0, s, id) $ getAllMatches $ match re s
        go (ind,read,write) (off,len) =
            let (skip, start) = splitAt (off - ind) read 
                (matched, remaining) = splitAt len start 
            in (off + len, remaining, write . (skip++) . (f matched ++))
Prelude> :set -XOverloadedStrings
Prelude> import Data.Text.ICU.Replace
Prelude Data.Text.ICU.Replace> replaceAll "cat" "dog" "Bailey is a cat, and Max is a cat too."
"Bailey is a dog, and Max is a dog too."