You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:35:38