0 %
!
Programmer
SEO-optimizer
English
German
Russian
HTML
CSS
WordPress
Python
C#
  • Bootstrap, Materialize
  • GIT knowledge
0

No products in the cart.

Regular Expressions in Parsing Data

21.01.2025

Advanced Regular Expression Techniques

While the basics of regular expressions are powerful, mastering advanced techniques can significantly enhance your ability to parse and manipulate text. Below are some advanced concepts and examples to help you take your regex skills to the next level.

1. Lookahead and Lookbehind Assertions

Lookahead and lookbehind assertions allow you to assert that a pattern is or isn’t followed by another pattern without including it in the match.

  • Positive Lookahead: (?=...)
    Asserts that the pattern inside the lookahead must follow the current position.
    Example:

    text = "100 dollars 200 euros"
    matches = re.findall(r'\d+(?=\s*dollars)', text)
    print(matches) # Output: ['100']

  • Negative Lookahead: (?!...)
    Asserts that the pattern inside the lookahead must not follow the current position.
    Example:

    text = "100 dollars 200 euros"
    matches = re.findall(r'\d+(?!\s*dollars)', text)
    print(matches) # Output: ['200']

  • Positive Lookbehind: (?<=...)
    Asserts that the pattern inside the lookbehind must precede the current position.
    Example:

    text = "100 dollars 200 euros"
    matches = re.findall(r'(?<=\$)\d+', text)
    print(matches) # Output: [] (no match, since there's no "$" before numbers)

  • Negative Lookbehind: (?<!...)
    Asserts that the pattern inside the lookbehind must not precede the current position.
    Example:

    text = "100 dollars 200 euros"
    matches = re.findall(r'(?<!\$)\d+', text)
    print(matches) # Output: ['100', '200']

2. Non-Capturing Groups

Non-capturing groups (?:...) allow you to group parts of a pattern without capturing the matched text. This is useful for applying quantifiers to groups without creating additional capture groups.

Example:

text = "hello world hello universe"
matches = re.findall(r'(?:hello\s)+(\w+)', text)
print(matches) # Output: ['world', 'universe']

3. Named Capture Groups

Named capture groups (?P<name>...) allow you to assign a name to a capture group, making it easier to reference the matched text.

Example:

text = "John Doe, Jane Smith"
matches = re.findall(r'(?P<first>\w+)\s(?P<last>\w+)', text)
for match in matches:
print(f"First: {match[0]}, Last: {match[1]}")

4. Conditional Patterns

Conditional patterns (?(condition)true-pattern|false-pattern) allow you to match different patterns based on whether a condition is met.

Example:

text = "123-456-7890 (123) 456-7890"
pattern = r'(\()?\d{3}(?(1)\)|-)\d{3}-\d{4}'
matches = re.findall(pattern, text)
print(matches) # Output: ['123-456-7890', '(123) 456-7890']

5. Greedy vs. Non-Greedy Matching

By default, quantifiers like * and + are greedy, meaning they match as much text as possible. Adding a ? after the quantifier makes it non-greedy, matching as little text as possible.

Example:

text = "<div>content</div><div>more content</div>"
greedy_match = re.findall(r'<div>.*</div>', text)
non_greedy_match = re.findall(r'<div>.*?</div>', text)
print(greedy_match) # Output: ['<div>content</div><div>more content</div>']
print(non_greedy_match) # Output: ['<div>content</div>', '<div>more content</div>']

6. Unicode and Multilingual Support

Regular expressions can handle Unicode characters, making them suitable for multilingual text processing. Use the \p{} syntax to match Unicode properties.

Example:

text = "Café 北京"
matches = re.findall(r'\p{L}+', text, re.UNICODE)
print(matches) # Output: ['Café', '北京']

7. Recursive Patterns

Recursive patterns allow you to match nested structures, such as balanced parentheses or HTML tags. This is achieved using (?R) or (?0) to refer to the entire pattern.

Example:

text = "(1 + (2 * (3 + 4)))"
pattern = r'\(([^()]+|(?R))*\)'
matches = re.findall(pattern, text)
print(matches) # Output: ['1 + 2 * 3 + 4']

8. Verbose Mode

Verbose mode allows you to write more readable regular expressions by ignoring whitespace and comments. Use the re.VERBOSE flag in Python.

Example:

pattern = r'''
^ # Start of string
[A-Za-z0-9._%+-]+ # Local part
@ # At symbol
[A-Za-z0-9.-]+ # Domain
\.[A-Z|a-z]{2,}$ # Top-level domain
'''
matches = re.findall(pattern, "support@example.com", re.VERBOSE)
print(matches) # Output: ['support@example.com']

9. Backreferences

Backreferences allow you to refer to previously captured groups within the same pattern. Use \1, \2, etc., to refer to the first, second, etc., capture group.

Example:

text = "hello hello world world"
matches = re.findall(r'(\b\w+\b)\s\1', text)
print(matches) # Output: ['hello', 'world']

10. Atomic Groups

Atomic groups (?>...) prevent backtracking within the group, which can improve performance and prevent certain types of matches.

Example:

text = "aaaaab"
pattern = r'(?>a+)ab'
matches = re.findall(pattern, text)
print(matches) # Output: [] (no match, since the atomic group prevents backtracking)

Conclusion

Advanced regular expression techniques open up a world of possibilities for text processing and manipulation. By mastering these concepts, you can handle more complex patterns, improve performance, and write more maintainable regex code. Whether you’re parsing nested structures, validating multilingual text, or optimizing performance, these techniques will help you tackle even the most challenging text processing tasks.

Keep experimenting and refining your regex skills to become a true text manipulation expert!

Posted in PythonTags:
Write a comment

You cannot copy content of this page