From a40f6e6c586f5ff27edb108def9a66cdf43b1e1a Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Sun, 11 Sep 2016 15:55:05 +0200 Subject: block-grep: search for patterns, grouped per block --- block-grep | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100755 block-grep diff --git a/block-grep b/block-grep new file mode 100755 index 0000000..5d10f72 --- /dev/null +++ b/block-grep @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# Searches block separated by multiple newlines. +# Originally written for filtering ASAN (LSan) reports. +# +# Example usage: +# ASAN_OPTIONS=log_path=$PWD/leak wireshark +# block-grep leak.1337 -e dbus -v | block-grep -e Direct + +import argparse +import re +import sys + +def is_leaked(lines): + return 'Objects leaked above:' in lines + +def parse_file(f, match_func): + lines = '' + last_matched = '' + def handle_lines(): + nonlocal last_matched + if match_func(lines): + sys.stdout.write(lines) + # Uncomment if you want to see the leaked objects too + #last_matched = lines + elif last_matched: + # If the previous block had a matching "Indirect leak of x bytes" + # and this block is its related "Objects leaked above", write it too + if 'irect leak of ' in last_matched and is_leaked(lines): + sys.stdout.write(lines) + last_matched = '' + for line in f: + lines += line + if line.strip('\r\n'): + continue + + handle_lines() + lines = '' + handle_lines() + +parser = argparse.ArgumentParser() +parser.add_argument('-e', '--regexp', dest='pattern') +parser.add_argument('-i', '--ignore-case', action='store_true') +parser.add_argument('-v', '--invert-match', action='store_true') +parser.add_argument('file', nargs='*') + +def main(): + args = parser.parse_args() + files = args.file + if not args.pattern: + if not files: + parser.error('Missing pattern option') + pattern = files.pop(0) + else: + pattern = args.pattern + + if not files: + files = ['-'] + + flags = 0 + if args.ignore_case: + flags |= re.IGNORECASE + pattern = re.compile(pattern, flags) + + match_func = lambda lines: pattern.search(lines) + if args.invert_match: + match_func = lambda lines: not pattern.search(lines) and not is_leaked(lines) + + for filename in files: + if filename == '-': + parse_file(sys.stdin, match_func) + else: + parse_file(open(filename, 'r'), match_func) + +if __name__ == '__main__': + try: + main() + except (KeyboardInterrupt, BrokenPipeError): + pass -- cgit v1.2.1