Skip to main content

A readable and intuitive way to generate Regular Expressions

Project description

EZRegex

A readable and intuitive way to write Regular Expressions without having to know any of the syntax

Table of Contents

Usage

Quickstart

TLDR: This is to regular expressions what CMake is to makefiles (i.e. it's a tool to generate the older tool's syntax)

from ezregex import *

'foo' + number + optional(whitespace) + group(word)
# Or if you prefer the method syntax (they can be mixed)
number.append(whitespace.optional).prepend('foo').append(word.group())

# These match `foo123abc` and `foo123 abc`
# but not `abc123foo` or  `foo bar`

Importing as a named package is recommended if you're using it in a larger project

import ezregex as ez

# ow is part of ez already as "optional chunk of whitespace" (`\s*`)
params = ez.group(ez.at_least_none(ez.ow + ez.word + ez.ow + ez.optional(',') + ez.ow))
# Seperate parts as variables for cleaner patterns
function = ez.word + ez.ow + '(' + params + ')'

function.search('some string containing func( param1 , param2)')

# Boolean test
'some string containing func( param1 , param2)' in function

# The test() method is helpful for debugging, and color codes groups for you
function.test('this should match func(param1,\tparam2 ), foo(), and bar( foo,)')

.test() will print all the matches, color coded to match and group (colors not shown here):

╭─────────────────────────────── Testing Regex ────────────────────────────────╮
│ Testing expression:                                                          │
│         \w+\s*\(((?:\s*\w+\s*,?\s*)*)\)                                      │
│ for matches in:                                                              │
│         this should match func(param1,  param2 ), foo(), and bar( foo,)      │
│                                                                              │
│ Match = "func(param1,   param2 )" (18:39)                                    │
│ Unnamed Groups:                                                              │
│         1: "param1,     param2 " (23:38)                                     │
│                                                                              │
│ Match = "foo()" (41:46)                                                      │
│ Unnamed Groups:                                                              │
│         1: "" (45:45)                                                        │
│                                                                              │
│ Match = "bar( foo,)" (52:62)                                                 │
│ Unnamed Groups:                                                              │
│         1: " foo," (56:61)                                                   │
│                                                                              │
│                                                                              │
╰─────────────────────────────────── Found  ───────────────────────────────────╯

Check out the gotchas for some common issues and gotchas.

Inverting

The invert function (available as ez.invert(expression), expression.invert(), or ~expression) is useful for debugging. You pass it an expression, and it returns an example of a string that is guaranteed to match the provided expression. It specifically is made for debugging as well, so where possible, it will use actual words and 12345... for sequences of numbers.

Generation

In version v1.7.0 we introduced a new function: generate_regex. It takes in 2 sets of strings, and returns a regular expression that will match everything in the first set and nothing in the second set. It may be a bit crude, but it can be a good starting point if you don't know where to start. It's also really good at regex golf.

Functions vs Methods

As of v2.1.0, elemental methods were added to EZRegex objects. These shadow their function element counterparts exactly and work the same way, they're just for convenience and preference.

For example, these are all equivelent:

# Element functions
optional(whitespace) + group(either(repeat('a'), 'b')) + if_followed_by(word)
# Elemental methods
whitespace.optional.append(literal('a').repeat.or_('b').group).if_followed_by(word)
# Mixed
whitespace.optional + repeat('a').or_('b').group + if_followed_by(word)

Dialects

As of version v1.6.0, the concepts of dialects was introduced. Different languages often have slight variations on the regular expression syntax. As this library is meant to be language independent (even though it's written in Python), you should be able to compile regular expressions to work with other languages as well. To do that, you can simply import all the elements as a sub-package, and they should work identically, although some languages may not have the same features as others.

>>> import ezregex as ez # The python dialect is the defualt dialect
>>> ez.group(digit, name='name') + ez.earlier_group('name')
PythonEZRegex((?P<name>\d)(?P=name), {...})
>>> import ezregex.javascript as ez
>>> ez.group(digit, name='name') + ez.earlier_group('name')
JavascriptEZRegex(/(?<name>\d)\k<name>/, {...})

The currently implemented dialects are:

Dialect Completeness Tests pass
Python ~100% Yes
JavaScript ~90% Yes
PCRE2 ~60% Yes
R 100% Yes
Rust 0% No
C# 0% No

Just because a dialect is implemented, doesn't mean it has all the features of the language. However, everything implemented is tested, so if you can import it, it's usable.

If you know a particular flavor of regex and would like to contribute, feel free to read the developer documentation and make a pull request! If you would like one that's not implemented yet, you can also add a github issue.

Utilities

All the functions in the Python re library (search, match, sub, etc.) are implemented in the Python dialect, and act identically to their equivalents. If you still want to use the Python re library directly, note that functions like search and sub don't accept EZRegex patterns as valid regex. Be sure to either call .str() (or cast it to a string) or .compile() (to compile to an re.Pattern) when passing to those. Using the member functions however, will be more efficient, as EZRegex caches the compiled re.Pattern internally.

There's also an api function, which acts like an API endpoint for regular expressions. This is used by the EZRegex frontend, as it loads this library locally in the browser. It made sense to put it in the library itself, becasue it could be useful for other purposes.

Aliases

A lot of the EZRegexs have multiple names, either because different names make more sense in different contexts, or simply to allow different formatting. You can see the aliases for each EZRegex in the docs. As a general rule, there are snake_case and camelCase versions for each one, where applicable.

Installation

EZRegex is distributed on PyPI as a pure-python universal wheel with no dependencies and is available on Linux, macOS and Windows and supports Python 3.10+ and PyPy.

pip install ezregex

The import name is the same as the package name:

import ezregex as ez

License

EZRegex is distributed under the MIT License

Contributing

I love contributions! I don't have many rules for contributing. I just ask that if you're going to add a dialect, before you open a PR, please set up tests for it, and make sure they pass. It doesn't have to be fully implemented, but it should at least be a valid framework to build off of.

Credits

This library was written from scratch entirely by Copeland Carter. Inspirations for this project include:

  • PyParsing
    • I stole a bunch of the operators (especially the [] operator) from them, though we happened upon the same basic structure independantly (convergent evolution, anyone?)
  • regular-expressions.info
    • Their reference is where I got a lot of the documentation on other regex dialects
  • human-regex
    • Gave me the idea for including element methods, instead of solely element functions
  • Peter Norvig and Stefan Pochmann
    • Peter Norvig's blog is where I ripped most of the generation code from. All credit goes to him.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ezregex-3.1.2.tar.gz (266.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ezregex-3.1.2-py3-none-any.whl (151.0 kB view details)

Uploaded Python 3

File details

Details for the file ezregex-3.1.2.tar.gz.

File metadata

  • Download URL: ezregex-3.1.2.tar.gz
  • Upload date:
  • Size: 266.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-httpx/0.28.1

File hashes

Hashes for ezregex-3.1.2.tar.gz
Algorithm Hash digest
SHA256 c9881cd3a4877bb35e893a5a9898c3fbd27eba6b765a3f81b15cbca2048e5fae
MD5 e63c70b6da66accdd1cf456bf348076f
BLAKE2b-256 3d2a9255c433baf9fae0ba722c57e6b1382d751762c4f927bddabb06fbdc559e

See more details on using hashes here.

File details

Details for the file ezregex-3.1.2-py3-none-any.whl.

File metadata

  • Download URL: ezregex-3.1.2-py3-none-any.whl
  • Upload date:
  • Size: 151.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-httpx/0.28.1

File hashes

Hashes for ezregex-3.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 b343457be10a638ea23fb69bd5cfe5ef0d7af3b6a32ed8a6bfbe7d802689b237
MD5 9884246f35e98733cb9b5be406bcb375
BLAKE2b-256 c033539f916f2da23f81fbe693aaac7b46663e1b0154b1481878b0b0001391ab

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page