Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
ctools/cgrep.py
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
executable file
209 lines (180 sloc)
5.91 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
from __future__ import print_function | |
#----------------------------------------------------------------------- | |
# Imports | |
#----------------------------------------------------------------------- | |
import sys | |
import getopt | |
#----------------------------------------------------------------------- | |
# Functions | |
#----------------------------------------------------------------------- | |
def Usage(msg=None): | |
print(""" | |
cgrep -iknq <str> <file> | |
cgrep -f <str_file> <file> | |
Search for matching 'clauses' in file. Clause is a block | |
of text separated by blank lines. | |
-f <str_file> Read strings from file. | |
-i Ignore case. | |
-k <key> Match <str> to entire value of <key> field. | |
-n Print line numbers. | |
-q Only print the first matching clause. | |
-v Print non-matching clauses. | |
-S Print output "KEY=VALUE\nKEY=VALUE" to set value in shell. | |
Run like: eval $(cgrep -k KEY VALSTR) | |
""") | |
if msg: print(msg) | |
raise SystemExit | |
# Read clauses | |
def read_clauses(files,lower_case=False): | |
line_no = 0 | |
for file in files: | |
clause = [] | |
# Open file | |
if file=="-": | |
fin = sys.stdin | |
else: | |
fin = open(file,"r") | |
for line in fin.readlines(): | |
line_no += 1 | |
line = line.strip() | |
# End of clause | |
if not line: | |
if clause: | |
yield clause | |
clause = [] | |
# Add line to clause | |
else: | |
if lower_case: | |
clause.append((line_no, line.lower())) | |
else: | |
clause.append((line_no, line)) | |
# Close file | |
if not file=="-": | |
fin.close() | |
# return last clause in file | |
if clause: | |
yield clause | |
clause = [] | |
def in_search_strings(val, search_strings, ignore_case=False): | |
if ignore_case: | |
return val.lower() in [s.lower() for s in search_strings] | |
else: | |
return val in [s for s in search_strings] | |
# Escape shell text strings so that we can still assign them to shell | |
# variables even if they contain: single quotes, double quotes, and/or spaces | |
def escape_shell_line(line): | |
# Return escaped string if it contains: single quote, double quote, or | |
# space | |
for c in line: | |
if c in (""" '" """): | |
return '"' + line.replace('"','\\"') + '"' | |
# Return original string | |
return line | |
# Read line like "LABEL: value" and return "LABEL=value" | |
# so string can be used by Unix shell to set shell variable | |
def get_kvformat(line): | |
# Get first split char | |
for pos, character in enumerate(line): | |
found = character in (' ',':') | |
if found: break | |
if found: | |
k = line[:pos] | |
v = line[pos+1:].strip() | |
return k + '=' + escape_shell_line(v) | |
else: | |
return line | |
#----------------------------------------------------------------------- | |
# Main | |
#----------------------------------------------------------------------- | |
# Initialize options | |
string_file = None | |
search_key = None | |
ignore_case = False | |
print_line_numbers = False | |
quiet = False | |
exclude = False | |
versbose = False | |
setvars = False | |
# Read options | |
opts, args = getopt.getopt(sys.argv[1:],"f:ik:nqvS") | |
for key,val in opts: | |
if key=='-f': | |
string_file = val | |
elif key=='-k': | |
search_key = val | |
elif key=='-i': | |
ignore_case = True | |
elif key=='-n': | |
print_line_numbers = True | |
elif key=='q': | |
quiet = True | |
elif key=='-v': | |
exclude = True | |
elif key=='-S': | |
setvars = True | |
# If not string_file, then read single search string from input line | |
if not string_file: | |
if len(args)<2: | |
Usage() | |
search_string, files = args[0], args[1:] | |
else: | |
if len(args)<1: | |
Usage() | |
files = args | |
# Get search strings from file | |
if string_file: | |
search_strings = [] | |
fin = open(string_file,"r") | |
for line in fin.readlines(): | |
line = line.strip() | |
if line: | |
search_strings.append(line) | |
else: | |
search_strings = (search_string,) | |
# If ignoring cause, convert all search strings to lowercase | |
if ignore_case: | |
search_strings = [s.lower() for s in search_strings] | |
if search_key: | |
search_key = search_key.lower() | |
# Look for a specific key and value - entire value must match | |
if search_key: | |
key_len = len(search_key)+1 | |
keys = (search_key+":", search_key+" ") | |
# Read clauses | |
for clause in read_clauses(files): | |
found = False | |
# Read line numbers and lines from clause | |
for line_no, line in clause: | |
# Search specific key (key of form "key:" or "key ") | |
if search_key: | |
if line[:key_len] in keys: | |
search_val = line[key_len:].strip() | |
if ignore_case: search_val.lower() | |
found = in_search_strings(search_val,search_strings) | |
if found: | |
break | |
# Search entire clause | |
else: | |
if ignore_case: | |
line = line.lower() | |
for search_string in search_strings: | |
if line.find(search_string)>=0: | |
found = True | |
break | |
# Search string found, so stop searching this clause. | |
if found: | |
break | |
# Print clause if string found. | |
if found ^ exclude: | |
for line_no, line in clause: | |
# Print line numbers with lines | |
if print_line_numbers: | |
print(line_no, line) | |
# Print lines only (default) | |
else: | |
if setvars: | |
print(get_kvformat(line)) | |
else: | |
print(line) | |
print() |