<img width="500" src="https://raw.githubusercontent.com/tfeldmann/simplematch/main/docs/simplematch.svg" alt="logo">
# simplematch
> Minimal, super readable string pattern matching for python.
[![PyPI Version][pypi-image]][pypi-url]
![PyPI - License](https://img.shields.io/pypi/l/simplematch)
[![tests](https://github.com/tfeldmann/simplematch/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/tfeldmann/simplematch/actions/workflows/tests.yml)
```python
import simplematch
simplematch.match("He* {planet}!", "Hello World!")
>>> {"planet": "World"}
simplematch.match("It* {temp:float}°C *", "It's -10.2°C outside!")
>>> {"temp": -10.2}
```
## Installation
`pip install simplematch`
(Or just drop the `simplematch.py` file in your project.)
## Syntax
`simplematch` has only two syntax elements:
- wildcard `*`
- capture group `{name}`
Capture groups can be named (`{name}`), unnamed (`{}`) and typed (`{name:float}`).
The following types are available:
- `int`
- `float`
- `email`
- `url`
- `ipv4`
- `ipv6`
- `bitcoin`
- `ssn` (social security number)
- `ccard` (matches Visa, MasterCard, American Express, Diners Club, Discover, JCB)
For now, only named capture groups can be typed.
Then use one of these functions:
```python
import simplematch
simplematch.match(pattern, string) # -> returns a `dict` on match, `None` otherwise.
simplematch.test(pattern, string) # -> returns `True` on match, `False` otherwise.
```
Or use a `Matcher` object:
```python
import simplematch as sm
matcher = sm.Matcher(pattern)
matcher.match(string) # -> returns a dict or None
matcher.test(string) # -> returns True / False
matcher.regex # -> shows the generated regex
```
## Basic usage
```python
import simplematch as sm
# extracting data
sm.match(
pattern="Invoice_*_{year}_{month}_{day}.pdf",
string="Invoice_RE2321_2021_01_15.pdf")
>>> {"year": "2021", "month": "01", "day": "15"}
# test match only
sm.test("ABC-{value:int}", "ABC-13")
>>> True
```
## Typed matches
```python
import simplematch as sm
matcher = sm.Matcher("{year:int}-{month:int}: {value:float}")
# extracting data
matcher.match("2021-01: -12.786")
>>> {"year": 2021, "month": 1, "value": -12.786}
# month is no integer -> no match and return `None`.
matcher.match("2021-AB: Hello")
>>> None
# no extraction, only test for match
matcher.test("1234-01: 123.123")
>>> True
# show generated regular expression
matcher.regex
>>> '^(?P<year>[+-]?[0-9]+)\\-(?P<month>[+-]?[0-9]+):\\ (?P<value>[+-]?(?:[0-9]*[.])?[0-9]+)$'
# show registered converters
matcher.converters
>>> {'year': <class 'int'>, 'month': <class 'int'>, 'value': <class 'float'>}
```
## Register your own types
You can register your own types to be available for the `{name:type}` matching syntax
with the `register_type` function.
`simplematch.register_type(name, regex, converter=str)`
- `name` is the name to use in the matching syntax
- `regex` is a regular expression to match your type
- `converter` is a callable to convert a match (`str` by default)
### Example
Register a `smiley` type to detect smileys (`:)`, `:(`, `:/`) and getting their moods:
```python
import simplematch as sm
def mood_convert(smiley):
moods = {
":)": "good",
":(": "bad",
":/": "sceptic",
}
return moods.get(smiley, "unknown")
sm.register_type("smiley", r":[\)\(\/]", mood_convert)
sm.match("I'm feeling {mood:smiley} *", "I'm feeling :) today!")
>>> {"mood": "good"}
```
## CLI Command
You can also install `simplematch` for use as a CLI command e.g. using `pipx`.
```sh
pipx install simplematch
```
### Usage
```sh
usage: simplematch [-h] [--regex] pattern [strings ...]
positional arguments:
pattern A matching pattern
strings The string to match
options:
-h, --help show this help message and exit
--regex Show the generated regular expression
```
### Example
Extract a date from a specific file name:
```sh
simplematch "Invoice_*_{year}_{month}_{day}.pdf" "Invoice_RE2321_2021_01_15.pdf"
>>> {"year": "2021", "month": "01", "day": "15"}
```
## Background
`simplematch` aims to fill a gap between parsing with `str.split()` and regular
expressions. It should be as simple as possible, fast and stable.
The `simplematch` syntax is transpiled to regular expressions under the hood, so
matching performance should be just as good.
I hope you get some good use out of this!
## Contributions
Contributions are welcome! Just submit a PR and maybe get in touch with me via email
before big changes.
## License
[MIT](https://choosealicense.com/licenses/mit/)
<!-- Badges -->
[pypi-image]: https://img.shields.io/pypi/v/simplematch
[pypi-url]: https://pypi.org/project/simplematch/
Raw data
{
"_id": null,
"home_page": "https://github.com/tfeldmann/simplematch",
"name": "simplematch",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8,<4.0",
"maintainer_email": "",
"keywords": "string,pattern,matching,regular,expression,regex",
"author": "Thomas Feldmann",
"author_email": "mail@tfeldmann.de",
"download_url": "https://files.pythonhosted.org/packages/d4/c5/209aa49f6c366f5b1d80e9eef2f75270079df3c9dec4658e0716e4bcd6ab/simplematch-1.4.tar.gz",
"platform": null,
"description": "<img width=\"500\" src=\"https://raw.githubusercontent.com/tfeldmann/simplematch/main/docs/simplematch.svg\" alt=\"logo\">\n\n# simplematch\n\n> Minimal, super readable string pattern matching for python.\n\n[![PyPI Version][pypi-image]][pypi-url]\n![PyPI - License](https://img.shields.io/pypi/l/simplematch)\n[![tests](https://github.com/tfeldmann/simplematch/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/tfeldmann/simplematch/actions/workflows/tests.yml)\n\n```python\nimport simplematch\n\nsimplematch.match(\"He* {planet}!\", \"Hello World!\")\n>>> {\"planet\": \"World\"}\n\nsimplematch.match(\"It* {temp:float}\u00b0C *\", \"It's -10.2\u00b0C outside!\")\n>>> {\"temp\": -10.2}\n```\n\n## Installation\n\n`pip install simplematch`\n\n(Or just drop the `simplematch.py` file in your project.)\n\n## Syntax\n\n`simplematch` has only two syntax elements:\n\n- wildcard `*`\n- capture group `{name}`\n\nCapture groups can be named (`{name}`), unnamed (`{}`) and typed (`{name:float}`).\n\nThe following types are available:\n\n- `int`\n- `float`\n- `email`\n- `url`\n- `ipv4`\n- `ipv6`\n- `bitcoin`\n- `ssn` (social security number)\n- `ccard` (matches Visa, MasterCard, American Express, Diners Club, Discover, JCB)\n\nFor now, only named capture groups can be typed.\n\nThen use one of these functions:\n\n```python\nimport simplematch\n\nsimplematch.match(pattern, string) # -> returns a `dict` on match, `None` otherwise.\nsimplematch.test(pattern, string) # -> returns `True` on match, `False` otherwise.\n```\n\nOr use a `Matcher` object:\n\n```python\nimport simplematch as sm\n\nmatcher = sm.Matcher(pattern)\n\nmatcher.match(string) # -> returns a dict or None\nmatcher.test(string) # -> returns True / False\nmatcher.regex # -> shows the generated regex\n```\n\n## Basic usage\n\n```python\nimport simplematch as sm\n\n# extracting data\nsm.match(\n pattern=\"Invoice_*_{year}_{month}_{day}.pdf\",\n string=\"Invoice_RE2321_2021_01_15.pdf\")\n>>> {\"year\": \"2021\", \"month\": \"01\", \"day\": \"15\"}\n\n# test match only\nsm.test(\"ABC-{value:int}\", \"ABC-13\")\n>>> True\n```\n\n## Typed matches\n\n```python\nimport simplematch as sm\n\nmatcher = sm.Matcher(\"{year:int}-{month:int}: {value:float}\")\n\n# extracting data\nmatcher.match(\"2021-01: -12.786\")\n>>> {\"year\": 2021, \"month\": 1, \"value\": -12.786}\n\n# month is no integer -> no match and return `None`.\nmatcher.match(\"2021-AB: Hello\")\n>>> None\n\n# no extraction, only test for match\nmatcher.test(\"1234-01: 123.123\")\n>>> True\n\n# show generated regular expression\nmatcher.regex\n>>> '^(?P<year>[+-]?[0-9]+)\\\\-(?P<month>[+-]?[0-9]+):\\\\ (?P<value>[+-]?(?:[0-9]*[.])?[0-9]+)$'\n\n# show registered converters\nmatcher.converters\n>>> {'year': <class 'int'>, 'month': <class 'int'>, 'value': <class 'float'>}\n```\n\n## Register your own types\n\nYou can register your own types to be available for the `{name:type}` matching syntax\nwith the `register_type` function.\n\n`simplematch.register_type(name, regex, converter=str)`\n\n- `name` is the name to use in the matching syntax\n- `regex` is a regular expression to match your type\n- `converter` is a callable to convert a match (`str` by default)\n\n### Example\n\nRegister a `smiley` type to detect smileys (`:)`, `:(`, `:/`) and getting their moods:\n\n```python\nimport simplematch as sm\n\ndef mood_convert(smiley):\n moods = {\n \":)\": \"good\",\n \":(\": \"bad\",\n \":/\": \"sceptic\",\n }\n return moods.get(smiley, \"unknown\")\n\nsm.register_type(\"smiley\", r\":[\\)\\(\\/]\", mood_convert)\n\nsm.match(\"I'm feeling {mood:smiley} *\", \"I'm feeling :) today!\")\n>>> {\"mood\": \"good\"}\n```\n\n## CLI Command\n\nYou can also install `simplematch` for use as a CLI command e.g. using `pipx`.\n\n```sh\npipx install simplematch\n```\n\n### Usage\n\n```sh\nusage: simplematch [-h] [--regex] pattern [strings ...]\n\npositional arguments:\n pattern A matching pattern\n strings The string to match\n\noptions:\n -h, --help show this help message and exit\n --regex Show the generated regular expression\n```\n\n### Example\n\nExtract a date from a specific file name:\n\n```sh\nsimplematch \"Invoice_*_{year}_{month}_{day}.pdf\" \"Invoice_RE2321_2021_01_15.pdf\"\n>>> {\"year\": \"2021\", \"month\": \"01\", \"day\": \"15\"}\n```\n\n## Background\n\n`simplematch` aims to fill a gap between parsing with `str.split()` and regular\nexpressions. It should be as simple as possible, fast and stable.\n\nThe `simplematch` syntax is transpiled to regular expressions under the hood, so\nmatching performance should be just as good.\n\nI hope you get some good use out of this!\n\n## Contributions\n\nContributions are welcome! Just submit a PR and maybe get in touch with me via email\nbefore big changes.\n\n## License\n\n[MIT](https://choosealicense.com/licenses/mit/)\n\n<!-- Badges -->\n\n[pypi-image]: https://img.shields.io/pypi/v/simplematch\n[pypi-url]: https://pypi.org/project/simplematch/\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Minimal, super readable string pattern matching.",
"version": "1.4",
"project_urls": {
"Homepage": "https://github.com/tfeldmann/simplematch",
"Repository": "https://github.com/tfeldmann/simplematch"
},
"split_keywords": [
"string",
"pattern",
"matching",
"regular",
"expression",
"regex"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "43092522a9249284657b80c35b5a06fda30d466f1065d387c05c0c7cf0bf4892",
"md5": "fdf48912df432c72ebf695f882251aa0",
"sha256": "e7b898e174bc11c3bddc1b1ee36a9d70dd96037295837a879195052c92107237"
},
"downloads": -1,
"filename": "simplematch-1.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "fdf48912df432c72ebf695f882251aa0",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8,<4.0",
"size": 6619,
"upload_time": "2023-10-05T14:45:07",
"upload_time_iso_8601": "2023-10-05T14:45:07.222407Z",
"url": "https://files.pythonhosted.org/packages/43/09/2522a9249284657b80c35b5a06fda30d466f1065d387c05c0c7cf0bf4892/simplematch-1.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "d4c5209aa49f6c366f5b1d80e9eef2f75270079df3c9dec4658e0716e4bcd6ab",
"md5": "90929c8f6ca861e3ca1c550470948aac",
"sha256": "55a77278b3d0686cb38e3ffe5a326a5f59c2995f1ba1fa1a4f68872c17caf4cb"
},
"downloads": -1,
"filename": "simplematch-1.4.tar.gz",
"has_sig": false,
"md5_digest": "90929c8f6ca861e3ca1c550470948aac",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8,<4.0",
"size": 5927,
"upload_time": "2023-10-05T14:45:08",
"upload_time_iso_8601": "2023-10-05T14:45:08.343475Z",
"url": "https://files.pythonhosted.org/packages/d4/c5/209aa49f6c366f5b1d80e9eef2f75270079df3c9dec4658e0716e4bcd6ab/simplematch-1.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-10-05 14:45:08",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "tfeldmann",
"github_project": "simplematch",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "simplematch"
}