# # add_dir "" # # add_file "grep.cc" # content [eead365196620a945d5e037eba4bac53804362c3] --- grep.cc +++ grep.cc @@ -0,0 +1,106 @@ +// 2006-04-13 Timothy Brownawell +// GPL v2 or greater +// +// link with boost_regex and boost_program_options +// +// grep.basic_io -p pattern -d delim [ -d delim ...] +// output stanzas that match pattern, stanzas start with delim +// for matching, an item is represented as key=value\nvalue2... +// attr "foo" "bar" +// would look like "attr=foo\nbar" +// the pattern must match the entire string +#include +#include +#include + +#include +#include + +#include "io.hh" + +using std::string; +using std::cout; +using std::cin; +using std::vector; + +namespace po = boost::program_options; + +using basic_io::stanza; +using basic_io::stanza_reader; + +struct stanza_matcher +{ + boost::regex re; + stanza_matcher(string const &s); + bool match(stanza const &s); +}; +stanza_matcher::stanza_matcher(string const &s) +{ + re = s; +} +bool +stanza_matcher::match(stanza const &s) +{ + using basic_io::item; + using basic_io::value; + for (vector::const_iterator i = s.items.begin(); + i != s.items.end(); ++i) + { + string str = i->key + "="; + bool first = true; + for (vector::const_iterator j = i->values.begin(); + j != i->values.end(); ++j) + { + if (!first) + str += "\n"; + str += j->parsed; + first = false; + } + if (boost::regex_match(str, re)) + return true; + } + return false; +} + + +int main(int argc, char **argv) +{ + po::options_description desc("Allowed options"); + desc.add_options() + ("help", "print this message") + ("pattern,p", po::value(), "pattern to find") + ("delim,d", po::value >(), "key that begins a stanza") + ("reverse,V", "output non-matching stanzas") + ; + po::variables_map vm; + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.count("help") || !vm.count("pattern") || !vm.count("delim")) + { + cout << desc << "\n"; + cout << "--pattern must be given once, " + << "and --delim must be given at least once.\n"; + return 1; + } + + stanza_matcher sm(vm["pattern"].as()); + + bool inverse(false); + if (vm.count("reverse")) + inverse = true; + + stanza st; + stanza_reader sr(cin, vm["delim"].as >()); + bool first = true; + while (sr.get(st)) + { + if (sm.match(st) != inverse) + { + if (!first) + cout<<"\n"; + cout << st; + first = false; + } + } +}