-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathregex-explained-quiz.py
More file actions
255 lines (236 loc) · 8.8 KB
/
Copy pathregex-explained-quiz.py
File metadata and controls
255 lines (236 loc) · 8.8 KB
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
"""
Quiz: Regex Explained
Review: concepts/regex-explained.md
"""
from _quiz_helpers import normalize_answer
def run_quiz():
print("=" * 60)
print(" QUIZ: Regex Explained")
print(" Review: concepts/regex-explained.md")
print("=" * 60)
print()
score = 0
total = 12
# Question 1
print("Question 1/12: Why should you use raw strings (r'...') for regex?")
print()
print(" a) They run faster")
print(" b) They prevent Python from interpreting backslashes before")
print(" the regex engine sees them")
print(" c) They are required by the re module")
print(" d) They support Unicode")
print()
answer = normalize_answer(input("Your answer: "))
if answer == "b":
score += 1
print("Correct! Without r, Python interprets \\b as backspace instead")
print("of a regex word boundary.")
else:
print("Incorrect. The answer is b).")
print("Raw strings pass backslashes through to the regex engine unchanged.")
print()
# Question 2
print("Question 2/12: What does \\d+ match?")
print()
print(" a) Exactly one digit")
print(" b) One or more digits")
print(" c) Zero or more digits")
print(" d) Only the digit 0")
print()
answer = normalize_answer(input("Your answer: "))
if answer == "b":
score += 1
print("Correct! \\d matches one digit, + means 'one or more'.")
print("So \\d+ matches '5', '42', '12345', etc.")
else:
print("Incorrect. The answer is b) one or more digits.")
print("\\d = digit, + = one or more.")
print()
# Question 3
print("Question 3/12: What is the difference between re.match() and")
print("re.search()?")
print()
print(" a) match() is case-insensitive, search() is case-sensitive")
print(" b) match() only checks the beginning of the string,")
print(" search() finds a match anywhere")
print(" c) match() returns all matches, search() returns the first")
print(" d) They are the same")
print()
answer = normalize_answer(input("Your answer: "))
if answer == "b":
score += 1
print("Correct! re.match(r'\\d+', 'hello 42') is None because the")
print("string does not START with digits. re.search() finds '42'.")
else:
print("Incorrect. The answer is b).")
print("match = beginning only. search = anywhere in the string.")
print()
# Question 4
print("Question 4/12: What does re.findall() return?")
print()
print(" a) The first match as a string")
print(" b) A match object")
print(" c) A list of all matching strings")
print(" d) True or False")
print()
answer = normalize_answer(input("Your answer: "))
if answer == "c":
score += 1
print("Correct! findall returns a list of all non-overlapping matches.")
else:
print("Incorrect. The answer is c) a list of all matching strings.")
print("re.findall(r'\\d+', 'a1 b22 c333') returns ['1', '22', '333'].")
print()
# Question 5
print("Question 5/12: What does the ? quantifier mean?")
print()
print(" a) Exactly one")
print(" b) Zero or one (optional)")
print(" c) One or more")
print(" d) Zero or more")
print()
answer = normalize_answer(input("Your answer: "))
if answer == "b":
score += 1
print("Correct! ? means the preceding element is optional.")
print("colou?r matches both 'color' and 'colour'.")
else:
print("Incorrect. The answer is b) zero or one.")
print("? makes something optional — it can appear 0 or 1 times.")
print()
# Question 6
print("Question 6/12: What do parentheses () create in a regex?")
print()
print(" a) Optional groups")
print(" b) Capturing groups that extract parts of the match")
print(" c) Comments")
print(" d) Alternation")
print()
answer = normalize_answer(input("Your answer: "))
if answer == "b":
score += 1
print("Correct! Groups let you extract specific parts of a match.")
print("Use match.group(1), match.group(2), etc. to access them.")
else:
print("Incorrect. The answer is b) capturing groups.")
print("(\\d{4})-(\\d{2}) captures the year and month separately.")
print()
# Question 7
print("Question 7/12: What does \\b match?")
print()
print(" a) A backspace character")
print(" b) A word boundary (the edge between a word and non-word character)")
print(" c) A blank line")
print(" d) A bold marker")
print()
answer = normalize_answer(input("Your answer: "))
if answer == "b":
score += 1
print("Correct! \\bcat\\b matches 'cat' as a whole word, not 'catalog'.")
print("Use raw strings (r'\\b') so Python does not interpret \\b as backspace.")
else:
print("Incorrect. The answer is b) a word boundary.")
print("\\b prevents matching inside longer words.")
print()
# Question 8
print("Question 8/12: What is the difference between greedy and lazy")
print("matching?")
print()
print(" text = '<b>bold</b> and <b>more</b>'")
print()
print(" a) Greedy matches as much as possible, lazy matches as little")
print(" b) Greedy is faster, lazy is slower")
print(" c) Greedy matches one character, lazy matches all")
print(" d) They produce the same result")
print()
answer = normalize_answer(input("Your answer: "))
if answer == "a":
score += 1
print("Correct! <b>.*</b> (greedy) matches '<b>bold</b> and <b>more</b>'.")
print("<b>.*?</b> (lazy, with ?) matches just '<b>bold</b>'.")
else:
print("Incorrect. The answer is a).")
print("Add ? after a quantifier to make it lazy: *? +? ??")
print()
# Question 9
print("Question 9/12: What does re.sub() do?")
print()
print(" a) Searches for a pattern")
print(" b) Replaces all matches of a pattern with a replacement string")
print(" c) Subtracts patterns")
print(" d) Creates a sub-pattern")
print()
answer = normalize_answer(input("Your answer: "))
if answer == "b":
score += 1
print("Correct! re.sub(pattern, replacement, text) replaces all matches.")
print("re.sub(r'\\d', 'X', 'abc123') gives 'abcXXX'.")
else:
print("Incorrect. The answer is b).")
print("sub = substitute. It replaces pattern matches with new text.")
print()
# Question 10
print("Question 10/12: What does the re.IGNORECASE flag do?")
print()
print(" a) Ignores whitespace in the pattern")
print(" b) Makes matching case-insensitive")
print(" c) Ignores errors")
print(" d) Ignores empty matches")
print()
answer = normalize_answer(input("Your answer: "))
if answer == "b":
score += 1
print("Correct! With re.IGNORECASE, 'python' matches 'Python',")
print("'PYTHON', 'python', etc.")
else:
print("Incorrect. The answer is b) case-insensitive matching.")
print()
# Question 11
print("Question 11/12: What happens if re.search() finds no match?")
print()
print(" a) Returns an empty string")
print(" b) Returns None")
print(" c) Raises an exception")
print(" d) Returns False")
print()
answer = normalize_answer(input("Your answer: "))
if answer == "b":
score += 1
print("Correct! search() returns None when no match is found.")
print("Always check 'if match:' before calling match.group().")
else:
print("Incorrect. The answer is b) None.")
print("Calling .group() on None raises AttributeError. Always check first.")
print()
# Question 12
print("Question 12/12: Why would you use re.compile()?")
print()
print(" a) To convert regex to a different format")
print(" b) To precompile a pattern for faster reuse in loops")
print(" c) To check if a pattern is valid")
print(" d) To compile Python code")
print()
answer = normalize_answer(input("Your answer: "))
if answer == "b":
score += 1
print("Correct! re.compile() creates a reusable pattern object.")
print("This is faster when the same pattern is used many times.")
else:
print("Incorrect. The answer is b).")
print("Compiled patterns avoid recompiling on every call in a loop.")
print()
# Final score
print("=" * 60)
pct = round(score / total * 100)
print(f" Final Score: {score}/{total} ({pct}%)")
print()
if pct == 100:
print(" Perfect! You understand regular expressions well.")
elif pct >= 70:
print(" Good work! Review the questions you missed.")
else:
print(" Keep practicing! Re-read concepts/regex-explained.md")
print(" and try again.")
print("=" * 60)
if __name__ == "__main__":
run_quiz()