-
Notifications
You must be signed in to change notification settings - Fork 0
/
grep.py
168 lines (137 loc) · 5.25 KB
/
grep.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
import argparse
import sys
import re
def output(line):
print(line)
def Index(pattern, lines, b_context, context, a_context):
index = []
new_index = []
for n, line in enumerate(lines):
find = re.search(pattern, line)
if find:
index.append(n)
if b_context > 0:
count = b_context
for x in index:
for j in range(count + 1):
y = x - (count - j)
if not y in new_index:
new_index.append(y)
if a_context > 0:
count = a_context
for x in index:
for j in range(count + 1):
y = x + j
if y < len(lines) and not y in new_index:
new_index.append(y)
if context > 0:
count = context
for x in index:
for j in range(count + 1):
y = x - (count - j)
if not y in new_index:
new_index.append(y)
for j in range(count + 1):
y = x + j
if y < len(lines) and not y in new_index:
new_index.append(y)
return new_index
def compare(pattern, line, case, invert):
flag = re.IGNORECASE if case else 0
match = bool(re.search(pattern, line, flag))
if invert:
match = not match
return match
def count(lines, params):
a = 0
for line in lines:
line = line.rstrip()
if compare(params.pattern, line, params.ignore_case, params.invert):
a += 1
output('{}'.format(a))
def grep(lines, params):
params.pattern = params.pattern.replace('?', '.').replace('*','.*?')
if params.count:
count(lines, params)
else:
if params.context or params.before_context or params.after_context:
valid_index = Index(params.pattern, lines, params.before_context,
params.context, params.after_context)
all_context=(params.context or params.before_context or params.after_context)
buffer = [None] * all_context
print(buffer)
after = 0
for n, line in enumerate(lines):
line = line.rstrip()
if compare(params.pattern, line, params.ignore_case, params.invert):
if params.line_number:
output('{}:{}'.format(n + 1, line))
else:
output('{}'.format(line))
elif params.context or params.before_context or params.after_context:
if n in valid_index:
if params.before_context or params.context:
for ind_buf,line_buf in enumerate(buffer):
if params.line_number:
if compare(params.pattern, line, params.ignore_case, params.invert):
line_buf = ('{}:{}'.format(n+1, line))
else:
line_buf = ('{}-{}'.format(n+1, line))
output(line_buf)
else:
line_buf = ('{}'.format(line))
output(line_buf)
buffer.pop(0)
buffer = [None] * all_context
after=params.after_context
if params.after_context:
after -= 1
if params.line_number:
line = ('{}-{}'.format(n+1, line))
output(line)
def parse_args(args):
parser = argparse.ArgumentParser(description='This is a simple grep on python')
parser.add_argument(
'-v', action="store_true", dest="invert", default=False, help='Selected lines are those not matching pattern.')
parser.add_argument(
'-i', action="store_true", dest="ignore_case", default=False, help='Perform case insensitive matching.')
parser.add_argument(
'-c',
action="store_true",
dest="count",
default=False,
help='Only a count of selected lines is written to standard output.')
parser.add_argument(
'-n',
action="store_true",
dest="line_number",
default=False,
help='Each output line is preceded by its relative line number in the file, starting at line 1.')
parser.add_argument(
'-C',
action="store",
dest="context",
type=int,
default=0,
help='Print num lines of leading and trailing context surrounding each match.')
parser.add_argument(
'-B',
action="store",
dest="before_context",
type=int,
default=0,
help='Print num lines of trailing context after each match')
parser.add_argument(
'-A',
action="store",
dest="after_context",
type=int,
default=0,
help='Print num lines of leading context before each match.')
parser.add_argument('pattern', action="store", help='Search pattern. Can contain magic symbols: ?*')
return parser.parse_args(args)
def main():
params = parse_args(sys.argv[1:])
grep(sys.stdin.readlines(), params)
if __name__ == '__main__':
main()