#
# 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;
+ }
+ }
+}