1

00:00:01,050  -->  00:00:08,160
Welcome to lesson 25 which roughly covers pages 154 to 157 of the automate the boring stuff with Python

2

00:00:08,190  -->  00:00:15,140
textbook the character that we went over in last lesson lets you match one of many possible groups in

3

00:00:15,200  -->  00:00:16,470
our regular expression.

4

00:00:16,530  -->  00:00:20,670
But you may also want to match a certain number of repetitions of the group.

5

00:00:20,790  -->  00:00:25,820
You may want to match at least one or more appearances of the group or you may want to match the group

6

00:00:25,830  -->  00:00:29,790
if it appears more than seven times but less than 10 times.

7

00:00:29,940  -->  00:00:35,340
In this lesson you'll learn the regular expression syntax for matching a specific number of repetitions

8

00:00:35,340  -->  00:00:35,770
.

9

00:00:35,850  -->  00:00:41,850
So to start off with I'm just going to import the r e regular expressions module and let's begin with

10

00:00:41,850  -->  00:00:43,560
the first character.

11

00:00:43,560  -->  00:00:49,600
The question mark character says match the preceding group 0 or 1 times each.

12

00:00:49,650  -->  00:00:50,760
It's an optional group.

13

00:00:50,760  -->  00:00:53,690
It can either appear once or not appear at all.

14

00:00:54,060  -->  00:00:55,260
Let's use some code.

15

00:00:55,260  -->  00:01:03,720
I'm going to use a Batman regular expression that I'll save in this bat rechecks variable so I'll call

16

00:01:03,750  -->  00:01:10,230
compile so that I'll return a regular expression object and the pattern I want this to match will either

17

00:01:10,230  -->  00:01:15,390
be that man or that woman.

18

00:01:16,020  -->  00:01:25,980
But in this case I could just make this a bit shorter by just saying adding a W.O. Whoa group and then

19

00:01:25,980  -->  00:01:27,800
a question mark after it.

20

00:01:27,840  -->  00:01:34,380
So this question Mark says this group rate here can appear in the in the text zero or 1 times in order

21

00:01:34,380  -->  00:01:36,440
to match this pattern.

22

00:01:37,290  -->  00:01:44,280
So if we call this railer expression objects search method and search string like the adventures of

23

00:01:44,310  -->  00:01:45,030
Batman

24

00:01:48,270  -->  00:01:53,640
we can see that this regular expression does indeed match this part of the string it found it found

25

00:01:53,700  -->  00:01:58,140
this pattern in this string and we see it match Batman.

26

00:01:58,140  -->  00:02:02,040
But this will also match the adventures of that woman

27

00:02:05,130  -->  00:02:12,710
because the W O group here can appear 1 or 0 times it appears 0 times here and appears once here.

28

00:02:12,920  -->  00:02:16,280
But if we had something like the adventures of bat.

29

00:02:16,530  -->  00:02:21,770
Whoa whoa whoa woman that actually doesn't match the pattern at all.

30

00:02:21,770  -->  00:02:24,440
Because it can only appear as 0 or 1 time.

31

00:02:24,450  -->  00:02:30,130
So the search method will return none to the variable.

32

00:02:30,810  -->  00:02:35,610
Using the earlier phone number example we can make a regular expression that looks for phone numbers

33

00:02:35,610  -->  00:02:40,070
that do or do not have an area code that is we can make the area code optional.

34

00:02:40,220  -->  00:02:46,800
So to enter this into the interactive shell going to create a regular expression object by calling compile

35

00:02:46,800  -->  00:02:47,580
and store it in.

36

00:02:47,580  -->  00:02:51,240
Phone read checks and the pattern for phone numbers.

37

00:02:51,240  -->  00:02:55,290
We can use that slash D which stands for any numeric digit.

38

00:02:55,680  -->  00:03:01,200
So we can have 3 digits for the area code three digits for the first part of the phone number and then

39

00:03:01,200  -->  00:03:05,430
the last four digits of the phone number.

40

00:03:05,460  -->  00:03:13,170
So this is the phone number rejects that requires a phone number to have an area code.

41

00:03:13,170  -->  00:03:22,900
So if I had a string my phone number is 4 1 5 5 5 5 1 2 3 4 Call me tomorrow.

42

00:03:24,120  -->  00:03:30,820
We'll just save that in the variable M-O because it will return a match object.

43

00:03:31,340  -->  00:03:34,180
We can see that this actually found the phone number with the area code.

44

00:03:34,200  -->  00:03:40,810
Except this pattern which requires the area code won't be able to match anything.

45

00:03:41,280  -->  00:03:46,910
If this stream doesn't have the area code so search returns None.

46

00:03:46,950  -->  00:03:51,330
So the most variable will contain the none value.

47

00:03:51,390  -->  00:03:59,580
So instead let's create a phone regular expression object that puts this area code into a group and

48

00:03:59,580  -->  00:04:04,710
then we have the question mark to say this preceding group is optional it can appear once or it can

49

00:04:04,710  -->  00:04:06,300
appear 0 times.

50

00:04:06,520  -->  00:04:16,740
And in this case we can see that the search method does return a match object for this phone number

51

00:04:16,980  -->  00:04:23,700
and also returns a match object for this phone number when it doesn't have an area code in front of

52

00:04:23,700  -->  00:04:25,170
it.

53

00:04:25,440  -->  00:04:30,840
And if you ever have to actually literally match a question mark as part of your pattern you can escape

54

00:04:30,870  -->  00:04:36,100
the question mark with a backslash in front of it.

55

00:04:44,860  -->  00:04:50,120
The asterisk character is usually called the star character in the context of regular expressions.

56

00:04:50,140  -->  00:04:54,510
And it means matches zero or more times.

57

00:04:54,550  -->  00:05:01,520
So let's go back to that Batman regular expression example creating that regular expression.

58

00:05:02,080  -->  00:05:09,430
And before we had the question mark here which meant that this W.O. could appear one or zero times we

59

00:05:09,430  -->  00:05:10,840
change that to a star.

60

00:05:10,840  -->  00:05:14,310
This means this can appear 0 or more times.

61

00:05:14,440  -->  00:05:22,080
So basically any number of times this will actually match the adventures of Batman string.

62

00:05:22,070  -->  00:05:28,780
It will also match the adventures of that woman string.

63

00:05:29,410  -->  00:05:37,300
And since it can accept any number of this w o group because the star means zero or more we say have

64

00:05:37,600  -->  00:05:45,560
several of that and it would still match that string.

65

00:05:46,480  -->  00:05:54,460
And if you need to match a literal star that appears as part of the pattern you can escape it with a

66

00:05:54,460  -->  00:05:57,170
backslash.

67

00:05:57,190  -->  00:06:03,880
So while the star character means matches 0 or more feet plus character means match one or more.

68

00:06:04,000  -->  00:06:09,190
So unlike the star which doesn't require its group to appear in the match string the group preceding

69

00:06:09,190  -->  00:06:11,350
a plus must appear at least once.

70

00:06:11,350  -->  00:06:18,730
It's not optional so it's created another Batman regular expression object by calling compile

71

00:06:22,720  -->  00:06:31,050
and let's say that that W.O. group is now required to show up here one or more times.

72

00:06:31,150  -->  00:06:37,630
This means that matching the adventures of Batman string it won't actually find that this string returns

73

00:06:37,860  -->  00:06:47,200
or this function call will return none over the adventures of that woman will match it because this

74

00:06:47,200  -->  00:06:52,160
w o group here of here is once and then also in this example with bat.

75

00:06:52,210  -->  00:07:00,820
Well we'll Wolman that will also match because that w o group can appear one or more times.

76

00:07:01,390  -->  00:07:08,530
And if you have to match a literal plus sign that appears in your pattern you can escape it with a backslash

77

00:07:10,330  -->  00:07:14,060
So let's have a quick example with that escaping.

78

00:07:14,080  -->  00:07:20,440
Let's say I'm just going to create a rejects object by calling compile and the pattern that I'm looking

79

00:07:20,440  -->  00:07:29,020
for is a literal plus sign followed by a literal star or asterisk followed by a literal question mark

80

00:07:33,160  -->  00:07:36,730
that would match a string that looks something like.

81

00:07:37,510  -->  00:07:48,760
I learned about plus star questionmark reject syntax and those that actually match these characters

82

00:07:48,780  -->  00:07:49,940
.

83

00:07:51,220  -->  00:07:57,490
So if you literally want to match these characters that otherwise have a special meaning for regular

84

00:07:57,490  -->  00:08:02,070
expression strings you can just precede them with a backslash to escape them.

85

00:08:02,080  -->  00:08:08,470
In fact we could even have something like putting this inside of a group and saying it has to appear

86

00:08:08,620  -->  00:08:14,230
one or more times by having a plus sign that means 0 one or more times

87

00:08:17,920  -->  00:08:21,880
and that would match a string that looks like this

88

00:08:21,880  -->  00:08:28,550
.

89

00:08:28,750  -->  00:08:33,640
So here it means literally I want you to find a plus sign that appears in the string that I'm looking

90

00:08:33,640  -->  00:08:39,760
for that's part of the text pattern and this is more of a regular expression instruction saying match

91

00:08:39,760  -->  00:08:44,700
one or more of this preceding group in the parentheses here.

92

00:08:46,010  -->  00:08:47,560
So here's a quick recap.

93

00:08:47,560  -->  00:08:56,280
The question mark means 0 or 1 the star means 0 or more and the plus sign means one or more.

94

00:08:56,410  -->  00:09:03,610
But let's say if you wanted to match a specific number of repetitions of a group we can do that in Python

95

00:09:03,610  -->  00:09:03,670
.

96

00:09:03,670  -->  00:09:11,770
I'm going to create a regular expression object that matches the string.

97

00:09:11,780  -->  00:09:20,750
Ha exactly three times and we can do that with curly braces with the number three in between them.

98

00:09:23,320  -->  00:09:28,020
So if we call the search method here we can search for.

99

00:09:29,290  -->  00:09:32,310
He said Ha Ha Ha

100

00:09:35,260  -->  00:09:40,140
we can see that this string is matched in the regular expression.

101

00:09:40,150  -->  00:09:46,710
This is kind of a simple example you might think well couldn't we just have something like.

102

00:09:46,710  -->  00:09:47,560
Ha ha ha.

103

00:09:47,570  -->  00:09:48,860
And this would work too.

104

00:09:48,850  -->  00:09:51,410
This would do the exact same thing as this.

105

00:09:51,960  -->  00:09:58,510
But the nice part about this syntax is that you could have something like say if you want to match multiple

106

00:09:58,510  -->  00:10:00,220
phone numbers.

107

00:10:04,110  -->  00:10:15,990
That either had or did not have the area code in front so that expression would look like this.

108

00:10:16,370  -->  00:10:23,370
We have the optional area code these are three digits and a dash for which can appear 0 or 1 times.

109

00:10:23,780  -->  00:10:26,850
And then we have the rest of the seven digits of the phone number.

110

00:10:26,850  -->  00:10:28,260
And then we get put all of that

111

00:10:30,800  -->  00:10:37,950
inside of a group and then just say we want this phone number we want to match three phone numbers in

112

00:10:37,950  -->  00:10:39,850
a row.

113

00:10:39,850  -->  00:10:41,840
Now that might look a little bit strange.

114

00:10:41,850  -->  00:10:46,780
Let's say they're also they have a comma that they're separated by.

115

00:10:47,270  -->  00:10:50,490
Except that comma is also optional.

116

00:10:51,140  -->  00:10:55,640
You could put that inside of a group and then say that comma is optional.

117

00:10:55,640  -->  00:10:57,570
So then this phone number red jacks

118

00:11:00,600  -->  00:11:18,160
would match a string like my numbers are 4 1 5 5 5 1 2 3 4 5 5 5 42 42 and 2 1 2 5 5 5 0 0 0 0.

119

00:11:18,750  -->  00:11:23,910
A really complicated looking pattern like this could be matched by this regular expression where we're

120

00:11:23,900  -->  00:11:32,310
looking for three phone numbers in a row which may or may not have the area code and may or may not

121

00:11:32,310  -->  00:11:39,410
have a comma following it that separates them.

122

00:11:39,410  -->  00:11:45,750
And remember this pattern would match exactly three of this complicated pattern just like we could have

123

00:11:46,370  -->  00:11:52,760
passed the string that has three has literally typed out instead of using this curly brace syntax.

124

00:11:52,830  -->  00:12:01,920
We could have just gotten rid of this and instead copy and paste this entire regular expression three

125

00:12:01,910  -->  00:12:08,720
times but then at this point it's getting kind of hard to read what exactly we mean from this regular

126

00:12:08,730  -->  00:12:15,590
expression and just we'd have to spend a lot of time kind of piecing together what this means.

127

00:12:15,810  -->  00:12:20,070
So the curly brace syntax really helps out on that front.

128

00:12:21,180  -->  00:12:23,890
Well let's say you wanted to match instead of three.

129

00:12:23,880  -->  00:12:28,880
You wanted to match a range of possible repetition so anywhere between three and five.

130

00:12:29,020  -->  00:12:31,710
I can just add a comma and then a second number.

131

00:12:31,740  -->  00:12:36,280
So then this becomes a minimum and maximum number of repetitions.

132

00:12:36,530  -->  00:12:39,730
So we can have a string like he said Ha ha ha.

133

00:12:39,770  -->  00:12:40,960
And that would match.

134

00:12:41,150  -->  00:12:45,470
We could also have four or five of these hands as well.

135

00:12:45,480  -->  00:12:49,550
And that would match if we had any more.

136

00:12:49,910  -->  00:12:53,980
Well this would still match but it would only match the first five.

137

00:12:54,020  -->  00:12:56,080
Ha ha ha ha's.

138

00:12:57,000  -->  00:13:02,120
And just like with slices if you leave off this first number or second number.

139

00:13:02,370  -->  00:13:06,890
In this case this is the same thing as saying zero to five.

140

00:13:08,120  -->  00:13:11,400
Or if you had three and then a comma followed by no number.

141

00:13:11,390  -->  00:13:13,920
This is the same as saying three or more.

142

00:13:13,940  -->  00:13:22,410
So there is an unbounded maximum you can have any number of these as long as it's at least three.

143

00:13:24,770  -->  00:13:26,990
So let's do a little experiment here.

144

00:13:27,020  -->  00:13:36,830
I'm going to create a regular expression that matches anywhere between 3 and 5 digits so that slash

145

00:13:36,840  -->  00:13:41,050
D was the regular expression syntax meaning any numeric digits.

146

00:13:41,070  -->  00:13:49,600
See I went to match a string that had between three and five of them.

147

00:13:49,600  -->  00:13:52,040
So I was going to call it and have it search the string.

148

00:13:52,080  -->  00:13:55,180
One two three four five six seven eight nine zero.

149

00:13:55,970  -->  00:14:02,060
You can see that what it matched right here was the first five digits.

150

00:14:02,100  -->  00:14:08,810
I mean it would technically match these five digits but pythons regular expressions start as soon as

151

00:14:08,820  -->  00:14:13,880
possible as the earliest match they can find is the match that they'll return.

152

00:14:13,880  -->  00:14:20,270
And also notice it could have matched these first three characters or the first four characters.

153

00:14:20,690  -->  00:14:23,090
But instead it matched the first five characters.

154

00:14:23,100  -->  00:14:29,780
And that's because by default regular expressions in Python do greedy matches this means that it tries

155

00:14:29,790  -->  00:14:34,720
to match the longest possible string that matches this pattern.

156

00:14:34,760  -->  00:14:43,140
So in an ambiguous situation like this string where it could match any three four or five digits regular

157

00:14:43,130  -->  00:14:48,780
expressions are going to match the maximum longest possible string.

158

00:14:48,770  -->  00:14:56,260
Now if you wanted to do a non-greedy match you can specify a question mark after that curly brace.

159

00:14:56,270  -->  00:15:02,540
So this question mark is different from the question mark that means 0 or 1 when it comes after a pattern

160

00:15:02,550  -->  00:15:07,560
like this as opposed to directly after a group.

161

00:15:07,560  -->  00:15:10,010
This means basically do a non-greedy match.

162

00:15:10,010  -->  00:15:16,620
So let's create this regular expression and then search that same 1 2 3 4 5 6 7 8 9 0 string and you

163

00:15:16,620  -->  00:15:21,510
see this time it matched the smallest possible string.

164

00:15:21,660  -->  00:15:25,010
This is a pattern that happens a lot in the regular expression syntax.

165

00:15:25,110  -->  00:15:31,850
If you add a question mark it'll do a non-greedy match whereas without it it'll just do a normal greedy

166

00:15:31,860  -->  00:15:32,220
match.

167

00:15:32,250  -->  00:15:35,450
We're trying to match the longest possible string.

168

00:15:36,240  -->  00:15:44,650
To recap the question mark matches a group 0 or 1 times the star matches a group 0 or more times.

169

00:15:44,800  -->  00:15:51,600
The plus matches a group one or more times and the curly braces can match a specific number of times

170

00:15:51,620  -->  00:15:51,660
.

171

00:15:51,680  -->  00:15:57,440
And if you put two numbers separated by a comma in between the curly braces you can have a minimum and

172

00:15:57,440  -->  00:15:59,090
maximum number of times.

173

00:15:59,120  -->  00:16:04,170
You can also leave out the first or second number inside the curly braces so that you can say that there

174

00:16:04,160  -->  00:16:10,850
is no met minimum or no maximum greedy matching matches the longest string possible.

175

00:16:10,880  -->  00:16:16,650
Well non-greedy matching matches the shortest string possible and putting a question mark after the

176

00:16:16,640  -->  00:16:21,960
curly braces makes it do a non-greedy match by default regular expression syntax.

177

00:16:22,160  -->  00:16:23,690
Does a greedy match
