使用parsec解析文本电子邮件

时间:2013-11-14 01:55:46

标签: haskell parsec

我刚开始学习Parsec并且......这有点大脑弯曲。 我有一封短信。我需要提取From:标题和正文。 现在,我开始寻找可以学习的教程和示例。我找到了三个,都处理解析CSV文件,好像世界上没有别的东西可以解析。

从理论上讲,它看起来非常简单:跳过行直到你点击以“From:”开头的行,并在“From:”和新行之间获取文本。在实践中,我已经和它斗争了几天。

Return-Path: <j.doe@gmail.com>
X-Original-To: j.doe@somedomain.biz
Delivered-To: j.doe@somedomsin.biz
blah ... blah ...
Subject: Test subject
From: John Doe <j.doe@gmail.com>
To: j.doe@somedomain.biz
Content-Type: multipart/alternative; boundary=047d7b2e4e3cdc627304eb094bfe

--047d7b2e4e3cdc627304eb094bfe
Content-Type: text/plain; charset=UTF-8

Email body

--047d7b2e4e3cdc627304eb094bfe

我可以定义像

这样的行
let line = do{many1 (noneOf "\n"); many1 newline}

我不明白如何循环直到我在一开始就用某个字符串击中一行?

p = do
  manyTill line (string "From:")
  string "From: "
  b <- many anyChar
  newline
  many line
  eof
  return b

这不起作用。 有人可以告诉我如何做或指向一个简单的教程(而不是CSV解析教程)。

如何提取主体,这是边界标记之间的文本,并在第一个空行之后开始?我认为提取身体更复杂,所以任何帮助都会受到赞赏。

由于

1 个答案:

答案 0 :(得分:1)

Parsec默认情况下不会回溯,因此many anyChar只会淹没你的其他文字。而是考虑像

这样的东西
manyTill line $ try (string "From: ")
b <- manyTill anyChar newline
many line
eof
return b

请注意,由于我们想要在end解析器失败并manyTill时回溯,因此务必确保其正确回溯,因此我们使用try

现在这仍然失败,因为您的电子邮件不以换行符结束,因此line开始成功,然后失败,导致整个解析器失败而不是回溯。如果您无法更改此内容而不是将其更改为

many (try line)

为了澄清,parsec认为如果解析器失败而没有默认消耗任何输入,则解析器会失败。如果它甚至消耗一个字符然后失败,那么整个解析器都会死掉。如果您想要回溯行为,那么这不会发生,请使用try

为了提取身体,

getBody = do
  manyTill anyChar (try $ string "boundary=")
  boundary <- manyTill anyChar newline
  manyTill anyChar (try $ string boundary) -- Get to the boundary
  manyTill anyChar (try $ string boundary) -- Read the body