moeglichst elegant logfile parsen
-
Hallo,
ich habe vor ein ASCII tcpdump logfile einzulesen, wobei eine Zeile folgendes Format hat:
18:12:27.808667 14744803536us tsft short preamble 54.0 Mb/s 2437 MHz (0x0480) -25dB signal -96dB noise antenna 1 71dB signal 44us 00:14:6c:0d:60:c2 (oui Unknown) > 00:18:4d:8a:b4:f6 (oui Unknown) Null Information, send seq 0, rcv seq 0, Flags [Command], length 1480
Zeilenweise einlesen tue ich das file mit:
std::string line; std::ifstream infile(filename, std::ios_base::in); while (getline(infile, line, '\n')) { // Zeile bearbeiten }
Nun habe ich bisher immer jede Zeile in std::strings tokens geteilt (Leerzeichen) und diese fuer weitere Verarbeitung in einen std::vectorstd::string gepusht. Allerdings brauche ich von der Zeile oben nur
54.0 00:14:6c:0d:60:c2 00:18:4d:8a:b4:f6 1480
Mein erster Gedanke war irgendwie scanf nachzubasteln
std::string input = "foo bar 10 20 hello 30" int a,b,c; std::string garbage; stringstream foo; foo << input; input >> garbage >> garbage >> a >> b >> garbage >> c;
finde das aber nicht sehr effizient.
Also meine Frage ist, wie ich aus der Zeile am elegantesten die Werte extrahiere die mich interessieren?
-
alpha21 schrieb:
Hallo,
ich habe vor ein ASCII tcpdump logfile einzulesen, wobei eine Zeile folgendes Format hat:
18:12:27.808667 14744803536us tsft short preamble 54.0 Mb/s 2437 MHz (0x0480) -25dB signal -96dB noise antenna 1 71dB signal 44us 00:14:6c:0d:60:c2 (oui Unknown) > 00:18:4d:8a:b4:f6 (oui Unknown) Null Information, send seq 0, rcv seq 0, Flags [Command], length 1480
Wenn die zeile gleich bleibt, leg ne while drüber und schmeiss die unnötigen teile wieder aus dem vector
string tmpstr = "aa bb cc"; istringstream iss(tmpstr); vector<string> parts; copy(istream_iterator<string>(iss),istream_iterator<string>(),back_inserter<vector<string>>(parts));
-
eine idee waere vielleicht:
class skip_strings { public: skip_strings(int val = 1) : value(val) { } std::istream& operator()(std::istream &in) { if(value == 0) return in; std::streambuf *buf = in.rdbuf(); char c = buf->sgetc(); do { while(std::isspace(c)) c = buf->snextc(); while(c != EOF && !std::isspace(c)) c = buf->snextc(); } while(--value); return in; } private: int value; }; std::string input = "foo bar 10 20 hello 30" int a,b,c; std::string garbage; stringstream foo; foo << input; input >> skip_strings(2) >> a >> b >> skip_strings(1) >> c;
ungetestet und aus dem kopf
Meep Meep
-
schöne idee, wie ich finde.
nur die zeileskip_strings(int val = 1) : value(val) { }
find ich doof.
- explicit vergessen?!
- wieso default-parameter? (wer soll später bei
stream >> skip_strings() >> ...
wissen, was dort passiert?) - wieso signed?
ich würde auch den namen in skip_dates oder so was in der richtung ändern.
skip_strings klingt so, als ob er aufhören würde, wenn er an einer zahl angelangt ist.bb
-
(1) ja
(2) keine ahnung wasich dabei gedacht habe
(3) sollte unsigned sein sonst muesste es 'if(value <= 0)' heissenMeep Meep
-
alpha21 schrieb:
std::string input = "foo bar 10 20 hello 30" int a,b,c; std::string garbage; stringstream foo; foo << input; input >> garbage >> garbage >> a >> b >> garbage >> c;
finde das aber nicht sehr effizient.
Vollkommen ausreichend und kommt ohne zusätzliches gefrickel aus.