我刚开始学习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解析教程)。
如何提取主体,这是边界标记之间的文本,并在第一个空行之后开始?我认为提取身体更复杂,所以任何帮助都会受到赞赏。
由于
答案 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