如何在Haskell中用另一个字符串替换一个字符串

21

我想用不同的字符串替换输入文件中的一个字符串。我正在寻找一种方法,但似乎我只能逐个字符地修改字符串。例如,在下面我的代码中

replace :: String -> String 
replace [] = [] 
replace (x:xs) = if x == '@' then 'y':replace xs --y is just a random char
                             else x:replace xs

searching :: String -> IO String
searching filename = do
    text <- readFile filename
    return(replace text)


main :: IO ()
main = do

  n <- searching "test.sf"
  writeFile "writefile.html" n 

我想要找到字符串 "@title" 的第一次出现,但是我似乎找不到一个方法来做到这一点,因为前面提到,我只能访问字符 '@'。是否有一种方法可以完成这样的任务。


1
我认为这个已经在这里讨论过了:https://dev59.com/-W7Xa4cB1Zd3GeqPqHna - kaan
1
这并不是真正的重复问题。另一个问题明确排除了使用其他库,而使用其他库是对这个问题的合理答案。 - C. A. McCann
针对此问题的通用解决方案:https://hackage.haskell.org/package/replace-megaparsec - James Brock
如果你想替换一个 Data.Text,请使用 replace - mb21
1个回答

22

你可以使用Data.List.Utils中的replace函数,它是惰性的,你可以使用以下代码在处理大文件时进行替换:

main = getContents >>= putStr . replace "sourceString" "destinationString"

这就是全部内容!

一个可能的替换函数可以是:

rep a b s@(x:xs) = if isPrefixOf a s

                     -- then, write 'b' and replace jumping 'a' substring
                     then b++rep a b (drop (length a) s)

                     -- then, write 'x' char and try to replace tail string
                     else x:rep a b xs

rep _ _ [] = []

另一种聪明的方式(来自Data.String.Utils)

replace :: Eq a => [a] -> [a] -> [a] -> [a]
replace old new l = join new . split old $ l

12
或者,使用Haskell平台的split包中的Data.List.Split,定义replace old new = intercalate new . splitOn old。将会替换旧的文本为新的文本。 - Conrad Parker
更好的选择是使用text包中的replace :: Text -> Text -> Text -> Text函数:http://hackage.haskell.org/package/text-1.2.3.0/docs/Data-Text.html#v:replace - Răzvan Flavius Panda

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接