summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2016-09-11 15:55:05 +0200
committerPeter Wu <peter@lekensteyn.nl>2016-09-11 15:55:05 +0200
commita40f6e6c586f5ff27edb108def9a66cdf43b1e1a (patch)
treefc773c97d4869b040a3c109321f20ae786f3b689
parent7851407fe89228897d01278bb1929f817821a701 (diff)
downloadscripts-a40f6e6c586f5ff27edb108def9a66cdf43b1e1a.tar.gz
block-grep: search for patterns, grouped per block
-rwxr-xr-xblock-grep78
1 files changed, 78 insertions, 0 deletions
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