如何使用attoparsec在Haskell中高效解析TXT电子书并统计句子数?
用attoparsec统计电子书句子数的完整实现
嘿,作为Haskell新手就敢上手attoparsec做文本解析,这步子迈得很扎实!我看了你给出的代码片段,帮你把它补全并优化,刚好能实现统计文本句子数量的需求。
首先咱们明确核心需求:句子一般是以.、!、?这类标点结尾,后面跟着空格或者换行(先暂时忽略Mr.这种缩写的复杂情况,先实现基础版本,之后再扩展)。
先给你补全并修正后的完整代码:
{-# LANGUAGE OverloadedStrings #-} import Data.Attoparsec.Text import qualified Data.Text as T import qualified Data.Text.IO as Txt import Control.Applicative ((<*>), (*>), (<$>), (<|>), pure) -- 可以用这个类型封装句子,或者直接用Text也没问题 data Sentence = Sentence T.Text deriving Show -- 匹配句子结尾的三种常见标点 sentenceEnd :: Parser Char sentenceEnd = char '.' <|> char '!' <|> char '?' -- 解析单个句子:读取到标点前的内容 → 匹配结尾标点 → 跳过后续空白 sentenceParser :: Parser Sentence sentenceParser = do -- 读取所有非结尾标点的字符,至少一个(避免空句子) content <- takeWhile1 (\c -> c /= '.' && c /= '!' && c /= '?') end <- sentenceEnd -- 跳过句子后面的空格、换行等空白字符 skipMany space -- 把内容和标点拼接,顺便去掉首尾空白 pure $ Sentence (T.strip content `T.snoc` end) -- 解析整个文本的所有句子 allSentencesParser :: Parser [Sentence] allSentencesParser = many1 sentenceParser <* endOfInput -- 主函数:读取文件、解析、输出句子数量 main :: IO () main = do -- 替换成你的电子书路径 inputTxt <- Txt.readFile "your-book.txt" case parseOnly allSentencesParser inputTxt of Left err -> putStrLn $ "解析出错啦: " ++ err Right sentences -> putStrLn $ "这本书总共有 " ++ show (length sentences) ++ " 个句子"
给你拆解一下关键部分:
- 你原来代码里的
optional其实不用自己定义,Control.Applicative里已经提供了这个函数,直接用就行 sentenceParser是核心:先抓句子的主体内容,再匹配结尾标点,最后跳过后面的空白(避免把换行或空格当成句子的一部分)allSentencesParser会把整个文本拆成句子列表,最后用endOfInput确保解析到文件末尾,避免遗漏- 主函数里用
parseOnly处理解析结果,成功就统计长度,失败就输出错误信息
如果之后想处理更复杂的场景,比如区分缩写和句子结尾,可以加一些规则:
- 比如检查句号后面的字符是不是大写字母(正常句子开头是大写)
- 或者预先定义常见的缩写列表,遇到这些缩写后面的句号就不认为是句子结尾
这个基础版本足够应付大部分普通文本的句子统计需求啦。
内容的提问来源于stack exchange,提问作者centrinok
相关产品推荐
相关产品推荐

