Concepts / Data Validation with Regular Expressions

Data Validation with Regular Expressions

Parentheses in regular expressions mark the portion of a match that findall() should extract and return.

  • Programming

Matching Versus Keeping

A regular expression can recognize more text than you ultimately want to keep. Parentheses solve this problem by marking the specific portion of a successful match that findall() should extract and return. The surrounding pattern still has to match, but the returned result can be only the text inside the parentheses.

findall() returns the groupX-:42full match42captured substring
What is the difference between the entire text matched by a regular expression and the smaller portion returned by a capturing group?

Parentheses do not change which text the pattern matches. They change which part of that match findall() returns.

Tracing findall() Results

What do you think happens?

A pattern matches the text X-:42. If the number is enclosed in parentheses, what will findall() return?

  • The full text X-:42
  • Only the text 42
  • An empty list
  • A number with integer type
Reveal answer

Answer: Only the text 42

The full pattern must match, but the parentheses identify 42 as the portion to extract. The extracted result is still a string.

matchfindall()matchfindall()X-:42input textpatternno parenthesesX-:42list of full matchespatternnumber in parentheses42list of captured strings
How does findall() change its output when a regular expression contains a capturing group?

Without parentheses, findall() returns the entire substring that matches the pattern. With one capturing group, findall() returns a list containing the strings captured by that group. Therefore, two patterns can match the same text while producing different findall() results.

Parentheses as Capture Boundaries

followed bycontainsends atX-:must match(capture startsnumbercaptured portion)capture ends
Which characters in the matched text are selected by the parentheses?

A capturing group is the part of a regular expression enclosed in parentheses. Text outside the group remains important because it must match for the overall pattern to succeed. However, findall() returns only the text represented by the group. The location of the parentheses in the pattern therefore determines which portion is extracted.

Extracting a Number From a Marked Line

Consider a line with the form X-:42 and a pattern whose number portion is enclosed in parentheses. What does findall() return?

Match the required structure: The line must contain the expected X- prefix, colon, and number. The pattern outside the parentheses participates in this match.

Identify the captured portion: The parentheses surround the number, so the number is the portion selected for extraction.

Read the findall() result: Because there is one capturing group, findall() returns a list of strings containing the captured number rather than the complete line.

The result contains the extracted number as a string, not as an integer.

Multiple Captured Values

A pattern can contain more than one set of parentheses. In that case, findall() returns a list of tuples. Each tuple contains the captured values in the order in which the groups appear in the pattern.

Keeping Two Parts of One Match

Suppose a line contains two portions that a pattern captures with two sets of parentheses. What shape should you expect from findall()?

Match the complete line structure: All required text, including the parts outside the parentheses, must match for the pattern to succeed.

Collect the first group: The first parenthesized portion becomes the first value in the result tuple.

Collect the second group: The second parenthesized portion becomes the second value in the same result tuple.

findall() returns a list of tuples, with captured values ordered by their groups in the pattern.

Pattern structurefindall() result shapeReturned content
No capturing groupListEntire matched substrings
One capturing groupList of stringsOnly the captured substrings
Multiple capturing groupsList of tuplesCaptured substrings in group order

The number of capturing groups changes both the content and structure of findall() results.

Converting Extracted Values

Every value extracted by findall() is a string, even when the characters look like a number. If later work requires arithmetic or comparisons using numeric values, convert the extracted strings explicitly to an appropriate type such as int or float.

Safe Result Handling

  • Treating the full match as the extracted value

    With a capturing group, findall() returns only the portion inside the parentheses.

    Fix: Identify which part of the pattern is enclosed in parentheses and use that as the expected extracted result.

  • Assuming an extracted number already has numeric type

    findall() always returns extracted values as strings.

    Fix: Convert the string explicitly when arithmetic or numeric comparison is needed.

  • Accessing a result before checking whether a match occurred

    For a nonmatching line, findall() returns an empty list.

    Fix: Verify that the returned list is non-empty before accessing one of its elements.

  • Expecting the same result shape for every number of groups

    With multiple groups, findall() returns a list of tuples.

    Fix: Use the number of capturing groups to predict the structure of the result.

When an input line does not match the pattern, findall() returns an empty list. A condition that checks whether the list contains at least one result prevents the program from trying to access a value that is not present.

Practice and Review

MEDIUM

For each situation, predict the result shape before writing any processing logic: a pattern with no parentheses, a pattern with one capturing group around the number, and a pattern with two capturing groups. Then decide which extracted values would need conversion before numeric use.

Hints
  • Ask whether findall() should return the complete match or only a captured portion.
  • Count the sets of parentheses in the pattern.
  • Remember that extracted values begin as strings.
  • Consider what happens if no input text matches.
  1. Parentheses define capturing groups in a regular expression. The complete pattern still controls whether a line matches, but findall() returns only the text inside the groups. One group produces a list of strings, while multiple groups produce a list of tuples. Extracted values are strings and may require conversion to int or float. When a line does not match, findall() returns an empty list, so check the result before accessing an element.

Key Takeaways

  • A regular expression can match a complete structure while a capturing group selects only the portion to extract.
  • findall() returns full matches without capturing groups and captured substrings when groups are present.
  • One capturing group produces a list of strings; multiple groups produce a list of tuples.
  • Extracted values are always strings and must be converted when another type is needed.
  • Check for a non-empty result before accessing extracted values.