如何在Haskell中查找和替换unicode字符?

时间:2017-07-12 21:13:53

标签: regex haskell unicode

我有一个unicode文件,其中包含MediaText标记中的(瑞典)维基百科文章。我想从所有标记中清除它。在某些情况下,我想从标记标记中提取文本,例如来自超链接的链接标题(如简化的wikiextractor)。

我的方法是在文件上运行一组正则表达式以删除标记。在链接示例中,我需要将[[link]]替换为link。只要文本不包含ö等unicode字符,我就可以使用正则表达式来解决这个问题。

我尝试过的例子:

ghci> :m +Data.Text
ghci> subRegex (mkRegex "\\[\\[([() a-zA-Z]*)\\]\\]") "Se mer om [[Stockholm]]" "\\1"
"Se mer om Stockholm"
ghci> subRegex (mkRegex "\\[\\[([() a-zA-Z]*)\\]\\]") "Se mer om [[Göteborg]]" "\\1"
"Se mer om [[G\246teborg]]"

为什么这不起作用?如何让正则表达式引擎意识到ö确实是一封普通的字母(至少在瑞典语中)?

修改 这个问题似乎不是真的存在于模式中,而是存在于引擎中。如果我允许链接文本中除q之外的所有字符,则可以允许ö。但不是这样......

ghci> subRegex (mkRegex "\\[\\[([^q]*)\\]\\]") "[[Goteborg]]" "\\1"
"Goteborg"
ghci> subRegex (mkRegex "\\[\\[([^q]*)\\]\\]") "[[Göteborg]]" "\\1"
"[[G\246teborg]]"
ghci> subRegex (mkRegex "ö") "ö" "q"
"q"
ghci> subRegex (mkRegex "[ö]") "ö" "q"
"\246"

使用字符类时,似乎会出现问题。它自己匹配ö

2 个答案:

答案 0 :(得分:2)

我现在决定按照作者撰写的SO Answer中的建议使用Text.Regex.PCRE.Heavy。它解决了我的问题。

因此,解决方案变为

GHCi, version 7.10.3: http://www.haskell.org/ghc/  :? for help
Prelude> :m Text.Regex.PCRE.Heavy
Prelude Text.Regex.PCRE.Heavy> :set -XFlexibleContexts
Prelude Text.Regex.PCRE.Heavy> :set -XQuasiQuotes
Prelude Text.Regex.PCRE.Heavy> gsub [re|\[\[([^\]]*)\]\]|] (\(firstMatch:_) -> firstMatch :: String) "[[Göteborg]]" :: String
"G\246teborg"

不幸的是,我仍然不知道为什么POSIX后端无法处理这个问题,但是PCRE后端可以。

答案 1 :(得分:0)

要在Haskell中查找并替换unicode字符,我们可以使用streamEdit函数,并使用Megaparsec解析器进行模式匹配(而不是正则表达式)。 Megaparsec letterChar解析器将匹配所有瑞典字母。

:set -XOverloadedStrings
import Text.Megaparsec
import Text.Megaparsec.Char
import Replace.Megaparsec
import Data.Text as T
import Data.Text.IO as T
import Data.Void

let wikilink :: Parsec Void T.Text [Char]
    wikilink = do
        _ <- chunk "[["
        fst <$> manyTill_ letterChar (chunk "]]")

T.putStr $ streamEdit wikilink T.pack "Se mer om [[Stockholm]]"
T.putStr $ streamEdit wikilink T.pack "Se mer om [[Göteborg]]"
Se mer om Stockholm
Se mer om Göteborg