2

我刚开始学习 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 解析教程)。

如何提取正文,即边界标记之间的文本并在第一个空行之后开始?我想提取尸体更加复杂,因此感谢您的帮助。

谢谢

4

1 回答 1

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
于 2013-11-14T03:40:06.480 回答