Wie parse csv mit boost::spirit
Habe ich diese csv-Zeile
std::string s = R"(1997,Ford,E350,"ac, abs, moon","some "rusty" parts",3000.00)";
Kann ich parse es mit boost::tokenizer
:
typedef boost::tokenizer< boost::escaped_list_separator<char> , std::string::const_iterator, std::string> Tokenizer;
boost::escaped_list_separator<char> seps('\\', ',', '\"');
Tokenizer tok(s, seps);
for (auto i : tok)
{
std::cout << i << std::endl;
}
Es ist richtig, außer token "rusty" haben sollten doppelte Anführungszeichen, die sind immer abgestreift.
Hier ist mein Versuch, die Verwendung von boost::spirit
boost::spirit::classic::rule<> list_csv_item = !(boost::spirit::classic::confix_p('\"', *boost::spirit::classic::c_escape_ch_p, '\"') | boost::spirit::classic::longest_d[boost::spirit::classic::real_p | boost::spirit::classic::int_p]);
std::vector<std::string> vec_item;
std::vector<std::string> vec_list;
boost::spirit::classic::rule<> list_csv = boost::spirit::classic::list_p(list_csv_item[boost::spirit::classic::push_back_a(vec_item)],',')[boost::spirit::classic::push_back_a(vec_list)];
boost::spirit::classic::parse_info<> result = parse(s.c_str(), list_csv);
if (result.hit)
{
for (auto i : vec_item)
{
cout << i << endl;
}
}
Probleme:
-
funktioniert nicht, druckt die erste token nur
-
warum boost::spirit::classic? kann nicht finden, Beispiele mit Geist V2
-
setup ist brutal .. aber damit kann ich Leben, mit dieser
** Ich möchte wirklich zu verwenden boost::spirit
weil es dazu neigt, ziemlich schnell
Erwartete Ausgabe:
1997
Ford
E350
ac, abs, moon
some "rusty" parts
3000.00
- Ich sehe nicht, wie Sie behandeln würde
""rusty""
als gültige Eingabe. Wenn quoted strings sind ok, dann würde ich erwarten, dass"embedded ""quotes"" like this"
, aber nicht unerwartet""
(leere Zeichenkette), vorkommend in einem Feld. - Ich habe bearbeitet den string-input, so dass die Anführungszeichen besser machen Sinn, hoffe ich.
- Ich glaube nicht, es macht jetzt mehr Sinn. Die Anzahl der Angebote ist unsymmetrisch. Warum nimmst du nicht die erwartete Leistung?
- Gerade gebucht und erwartete Ausgabe
- Ich glaube nicht, dass es eine vernünftige Art und Weise zu interpretieren, dass die Eingabe auf diese Weise. Die 'embedded' Zitate müssen escaped werden (
""
oder z.B.\"
) die eine oder andere Weise, sonst wird der scan nicht möglich zu entscheiden, ob das Ende der Zeichenkette erreicht wurde? Ich denke nicht, dass eine CSV-engine behandelt es dieser Weg. - Wenn Sie MS Excel ersetzen Sie das Trennzeichen durch Tabulatoren kopieren Sie die Zeile und fügen Sie in einem Excel-sheet. Es ist korrekt analysiert
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sehe die post sieht ein gutes Stück sauberer aus, als meine, aber ich war putting dies zusammen für ein bisschen, so ist es hier sowieso:
Und dieser Ausgänge:
Erwähnenswert: Diese nicht implementieren eine vollständige CSV-parser. Sie würde auch wollen, zu schauen escape-Zeichen oder was auch immer sonst benötigt wird, für Ihre Umsetzung.
Auch: Wenn Sie auf der Suche in der Dokumentation, nur damit Sie wissen, mit Qi,
'a'
entsprichtboost::spirit::qi::lit('a')
und"abc"
entsprichtboost::spirit::qi::lit("abc")
.Auf Doppelte Anführungszeichen: So, als Sehe die Noten in einem Kommentar oben, es ist nicht direkt klar, was die Regeln, um ein
""
im input-text bedeutet. Wenn Sie wollte, dass alle Instanzen von""
nicht innerhalb einer in Anführungszeichen eingeschlossenen Zeichenkette umgewandelt werden, um eine"
, dann so etwas wie die folgenden funktionieren würde.{''}
, aber andere vielleicht erwarten, dass ein leerer vector{}
.Adressierung genau Ihre Frage, vorausgesetzt entweder zitiert oder nicht börsennotierten Felder (keine teilweise Zitate innen Feld Werte), mit Geist, V2:
Nehmen wir das einfachste 'abstrakter Datentyp', die möglicherweise funktionieren kann:
Sowie die wiederholte double-quote entweicht ein double-quote-Semantik (wie ich schon in dem Kommentar), Sie sollten in der Lage sein, etwas zu verwenden, wie:
Folgende komplette test-Programm druckt
(Hinweis: die BOOST_SPIRIT_DEBUG definieren, für die einfaches Debuggen). Sehen Sie Live auf Coliru
Full Demo
using
Klauseln)#define
füreol
? Versuchen Sie, mit expliziten Qualifikationen wieqi::eol
: ideone.com/VVVTYe. (Ich hasse, wie ich psi-debug-compiler/library Probleme hier)splitInto
- Funktion-Schnittstelle bereit gestellt. Gute Nacht*~char_(colsep)
sollte so etwas wie*~char_(",\n")
so, dass die Spalten nicht zu verbrauchen, das newline!*(char_ - eol - ',')
wäre sauberer