Apply scoped flags to subpatterns
hg(?flags-flags:...). This allows you to turn flags on or off for a specific part of the expression.(?flags-flags:...)repository·hg·Indexed 20 days ago
https://github.com/mrabarnett/mrab-regexA high-performance Python regular expression module designed as an alternative to 're'. It provides backwards compatibility with the standard library while adding advanced features such as nested sets, full Unicode case-folding, recursive patterns, fuzzy matching, and partial matches. The module supports 94 Unicode properties (including Script, Block, and General Category) and can release the GIL during matching on immutable strings via the concurrent=True argument.
(?flags-flags:...). This allows you to turn flags on or off for a specific part of the expression.(?flags-flags:...)You can perform set operations within a character set [...]. The operators, in order of increasing precedence, are:
||: Union (e.g., [a||b])~~: Symmetric difference (e.g., [x~~y] is x or y, but not both)&&: Intersection (e.g., [a&&b])--: Difference (e.g., [a--b] is a but not b)Implicit union (simple juxtaposition like [ab]) has the highest precedence.
# Examples of set operations
# [[a-z]--[qw]] -> all lowercase letters except q and w
# [\p{ASCII}&&\p{Letter}] -> ASCII lettersThe regex module provides advanced Unicode support:
Use \N{name} to match specific Unicode characters (requires support in Python's Unicode database).
Use \p{property=value}, \P{property=value}, \p{value}, or \P{value} to match characters based on Unicode properties.
\p{property:value} or \p{property=value} matches a character with that property.\P{...} or \p{^...} is the inverse.\p{value} checks properties in order: General_Category, Script, Block, then binary properties.Short form prefixes:
Is<Name>: Matches a script or binary property (e.g., \p{IsLatin} for Script=Latin).In<Name>: Matches a block (e.g., \p{InBasicLatin} for Block=BasicLatin).\p{Latin}
\p{InBasicLatin}
\p{IsAlphabetic}Unlike the standard re module, regex allows you to use the same name for multiple groups.
group(name): Returns the last capture of that named group.captures(name): Returns a list of all captures for that named group.# Both groups capture, the second capture 'overwrites' the first in .group()
# but both are preserved in .captures()
m = regex.match(r"(?P<item>\w+)? or (?P<item>\w+)?", "first or second")
print(m.group("item")) # 'second'
print(m.captures("item")) # ['first', 'second']All groups have a group number starting from 1.
Key Rules:
.captures() method of the match object.(?|...): Group numbers are reused across different branches. If groups in different branches have different names, they will have different numbers.Example of branch reset numbering:
In (\s+)(?|(?P<foo>[A-Z]+)|(\w+) (?P<foo>[0-9]+)), there are 2 groups:
(\s+) is group 1.(?P<foo>[A-Z]+) and (\w+) (?P<foo>[0-9]+) are group 2 because of the branch reset and the shared name foo.The branch reset syntax (?|...|...) allows group numbers to be reused across different alternatives in a pattern. However, if alternatives contain groups with different names, they will still have distinct group numbers.
>>> import regex
>>> regex.match(r"(?|(first)|(second))", "first").groups()
('first',)
>>> regex.match(r"(?|(first)|(second))", "second").groups()
('second',)The regex module provides two modes to ensure compatibility with the standard re module while offering enhanced features.
Indicated by the VERSION0 flag. This mode mimics the standard re module.
re before Python 3.7 (.split won't split at zero-width; .sub advances by one character).Indicated by the VERSION1 flag. This is the enhanced mode.
If no version is specified, the module defaults to regex.DEFAULT_VERSION.
Possessive quantifiers match a subpattern up to a specified limit and do not allow the engine to backtrack into them if the subsequent pattern fails. This is equivalent to using an atomic group (?>(?:...)+).
Supported syntax:
(?:...)?+ (possessive optional)(?:...)*+ (possessive zero or more)(?:...)++ (possessive one or more)(?:...){min,max}+ (possessive range)(?:...)++In Version 1 behavior (indicated by VERSION1), you can use nested sets and set operations (like subtraction). This is not possible in Version 0.
Example of set subtraction in Version 1:
[[a-z]--[aeiou]] matches any lowercase letter except vowels.
In Version 0, the same pattern [[a-z]--[aeiou]] is interpreted literally as a set containing [ and a-z, followed by --, then a set of aeiou, and finally ].
POSIX character classes are supported using the [[:class:]] syntax. These are often treated as alternatives to Unicode properties, though some definitions differ from Unicode.
Mappings:
[[:alnum:]] $\rightarrow$ \p{posix_alnum}[[:digit:]] $\rightarrow$ \p{posix_digit}[[:punct:]] $\rightarrow$ \p{posix_punct}[[:xdigit:]] $\rightarrow$ \p{posix_xdigit}Syntax:
[[:alpha:]][[:^alpha:]] (negated)[[:alpha:]]
[[:^alpha:]]Partial matches allow you to determine if a string could potentially match a pattern if it were not truncated. This is useful for real-time validation (e.g., checking a user's input character-by-character).
To use this feature, pass the partial=True keyword argument to match(), search(), fullmatch(), or finditer().
Match objects returned via partial matching will have a partial attribute set to True. A complete match will have partial=False (or the attribute will be absent depending on the specific method call context, but the example shows False for complete matches).
pattern = regex.compile(r'\d{4}')
# Partial match: matches '123' but expects more digits
print(pattern.fullmatch('123', partial=True))
# <regex.Match object; span=(0, 3), match='123', partial=True>
# Complete match: matches '1234' exactly
print(pattern.fullmatch('1234', partial=True))
# <regex.Match object; span=(0, 4), match='1234'>
# Check the attribute on a match object
print(pattern.match('123', partial=True).partial)
# Truere module, the regex module allows lookbehind assertions to match strings of variable length.