#!/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