plicate whole word similarlyif the input text was "one and and two let' say"without the last assertion there would be two matches and two capturesone and and two let' say the use of the lookahead assertion means that the second word matched is whole wordso we end up with one match and one captureone and and two let' say the for loop iterates over every match object returned by the finditer(method and we use the match object' group(method to retrieve the captured group' text we could just as easily (but less maintainablyhave used group( )--in which case we need not have named the capture group at all and just used the regex \ (\ +)\ +\ (?!\wanother point to note is that we could have used word boundary \ at the endinstead of (?!\wanother example we presented earlier was regex for finding the filenames in html image tags here is how we would compile the regexadding flags so that it is not case-sensitiveand allowing us to include commentsimage_re re compile( ""<img\sstart of tag [^>]*non-src attributes srcstart of src attribute (?(? ["']opening quote (? [^\ >]+?image filename (? =quoteclosing quote ---or alternatively--(? [^">]+unquoted image filename [^>]*non-src attributes end of the tag """re ignorecase|re verboseimage_files [for match in image_re finditer(text)image_files append(match group("qimage"or match group("uimage")again we use the finditer(method to retrieve each match and the match object' group(function to retrieve the captured texts each time match is made we don' know which of the image groups ("qimageor "uimage"has matchedbut using the or operator provides neat solution for this since the case insensitivity applies only to img and srcwe could drop the re ignorecase flag and use [ii][mm][ggand [ss][rr][ccinstead although this would make the regex less clearit might make it faster since it would not require the text being matched to be set to upper(or lower-case--but it is likely to make difference only if the regex was being used on very large amount of text