2

csvファイルを文字列のテーブルに解析するための次のParsecパーサーを定義しました。[[String]]

--A csv parser is some rows seperated, and possibly ended, by a newline charater
csvParser = sepEndBy row (char '\n')
--A row is some cells seperated by a comma character
row = sepBy cell (char ',')
--A cell is either a quoted cell, or a normal cell
cell = qcell <|> ncell
--A normal cell is a series of charaters which are neither , or newline. It might also be an escape character
ncell = many (escChar <|> noneOf ",\n")
--A quoted cell is a " followd by some characters which either are escape charaters or normal characters except for "
qcell = do
    char '"'
    res <- many (escChar <|> noneOf "\"")
    char '"'
    return res
--An escape character is anything followed by a \. The \ will be discarded.
escChar = char '\\' >> anyChar

コメントが多すぎて迷惑なのか、助けになっているのか、よくわかりません。パーセクの初心者として、彼らは私を助けてくれるので、私はそれらを追加しようと思いました.

それはかなりうまく機能しますが、問題があります。テーブルに余分な空の行が作成されます。したがって、たとえば、10 行 (つまり、10 行のみ。最後に空の行はありません*) の csv ファイルがある場合、[[String]]構造の長さは 11 になり、s の最後のリストにStringは 1 つの要素が含まれます。空String(少なくとも、 を使用して印刷すると、このように表示されますshow)。

私の主な質問は、この余分な行が表示されるのはなぜですか?それを止めるにはどうすればよいですか?

私が指摘したもう1つのことは、csvファイルのデータの後に空の行がある場合、これらはStringテーブルに空の行のみを含む行として終了することです. sepEndByの代わりに使用sepByすると、余分な空行が無視されると思いました。そうではありませんか?

*16進エディタでテキストファイルを見た後、vimがそれを表示していなくても、実際には実際には改行文字で終わっているようです...

4

1 に答える 1

3

各行に少なくとも1つのセルを含める場合は、sepBy1の代わりにを使用できますsepBy。これにより、空の行が行として解析されるのも停止するはずです。との違いは、との違いsepBysepBy1同じです。バージョンは、少なくとも1つの要素のシーケンスのみを解析します。だからこれになります:manymany11row

row = sepBy1 cell (char ',')

また、通常のスタイルはsepBy1中置で使用することです:cell `sepBy1` char ','。これはより自然に読み取れます。「セルでコンマで区切る」ではなく、「セルをコンマで区切る」ということです。

編集:空のセルを受け入れたくない場合は、:ncellを使用して少なくとも1つの文字を含むセルを指定する必要があります。many1

ncell = many1 (escChar <|> noneOf ",\n")
于 2012-07-23T19:36:38.397 に答える