{"id":18345116,"url":"https://github.com/chrispenner/lens-regex-pcre","last_synced_at":"2025-04-13T09:40:44.068Z","repository":{"id":56845532,"uuid":"191020370","full_name":"ChrisPenner/lens-regex-pcre","owner":"ChrisPenner","description":"Text lenses using PCRE regexes","archived":false,"fork":false,"pushed_at":"2020-10-11T03:56:18.000Z","size":3853,"stargazers_count":126,"open_issues_count":2,"forks_count":1,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-04-26T01:01:59.246Z","etag":null,"topics":["hacktoberfest","lenses","regex"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ChrisPenner.png","metadata":{"files":{"readme":"README.md","changelog":"ChangeLog.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-06-09T15:03:49.000Z","updated_at":"2023-03-06T16:07:37.000Z","dependencies_parsed_at":"2022-09-17T11:02:14.259Z","dependency_job_id":null,"html_url":"https://github.com/ChrisPenner/lens-regex-pcre","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChrisPenner%2Flens-regex-pcre","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChrisPenner%2Flens-regex-pcre/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChrisPenner%2Flens-regex-pcre/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChrisPenner%2Flens-regex-pcre/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ChrisPenner","download_url":"https://codeload.github.com/ChrisPenner/lens-regex-pcre/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248693193,"owners_count":21146749,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest","lenses","regex"],"created_at":"2024-11-05T21:07:17.497Z","updated_at":"2025-04-13T09:40:44.045Z","avatar_url":"https://github.com/ChrisPenner.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# lens-regex-pcre\n\n[Hackage and Docs](http://hackage.haskell.org/package/lens-regex-pcre)\n\nBased on `pcre-heavy`; so it should support any regexes or options which it supports.\n\nPerformance is [equal, sometimes **better**](https://github.com/ChrisPenner/lens-regex-pcre#performance) than that of `pcre-heavy` alone.\n\nWhich module should you use?\n\nIf you need unicode support, use `Control.Lens.Regex.Text`, if not then `Control.Lens.Regex.ByteString` is faster.\n\nWorking with Regexes in Haskell kinda sucks; it's tough to figure out which libs\nto use, and even after you pick one it's tough to figure out how to use it; `lens-regex-pcre` hopes to replace most other solutions by being fast, easy to set up, more adaptable with a more consistent interface.\n\nIt helps that there are already HUNDREDS of combinators which interop with lenses :smile:.\n\nAs it turns out; regexes are a very lens-like tool; Traversals allow you to select\nand alter zero or more matches; traversals can even carry indexes so you know which match or group you're working\non.\n\n# Examples\n\n```haskell\nimport Control.Lens.Regex.Text\n\ntxt :: Text\ntxt = \"raindrops on roses and whiskers on kittens\"\n\n-- Search\n\u003e\u003e\u003e has [regex|whisk|] txt\nTrue\n\n-- Get matches\n\u003e\u003e\u003e txt ^.. [regex|\\br\\w+|] . match\n[\"raindrops\",\"roses\"]\n\n-- Edit matches\n\u003e\u003e\u003e txt \u0026 [regex|\\br\\w+|] . match %~ T.intersperse '-' . T.toUpper\n\"R-A-I-N-D-R-O-P-S on R-O-S-E-S and whiskers on kittens\"\n\n-- Get Groups\n\u003e\u003e\u003e txt ^.. [regex|(\\w+) on (\\w+)|] . groups\n[[\"raindrops\",\"roses\"],[\"whiskers\",\"kittens\"]]\n\n-- Edit Groups\n\u003e\u003e\u003e txt \u0026 [regex|(\\w+) on (\\w+)|] . groups %~ reverse\n\"roses on raindrops and kittens on whiskers\"\n\n-- Get the third match\n\u003e\u003e\u003e txt ^? [regex|\\w+|] . index 2 . match\nJust \"roses\"\n\n-- Match integers, 'Read' them into ints, then sort them in-place\n-- dumping them back into the source text afterwards.\n\u003e\u003e\u003e \"Monday: 29, Tuesday: 99, Wednesday: 3\" \n   \u0026 partsOf ([regex|\\d+|] . match . unpacked . _Show @Int) %~ sort\n\"Monday: 3, Tuesday: 29, Wednesday: 99\"\n\n```\n\nBasically anything you want to do is possible somehow.\n\n# Performance\n\nSee the [benchmarks](https://github.com/ChrisPenner/lens-regex-pcre/blob/master/bench/Bench.hs).\n\n## Summary\n\nCaveat: I'm by no means a benchmarking expert; if you have tips on how to do this better I'm all ears!\n\n* **Search** `lens-regex-pcre` is *marginally* slower than `pcre-heavy`, but well within acceptable margins (within 0.6%)\n* **Replace** `lens-regex-pcre` beats `pcre-heavy` by ~10%\n* **Modify** `pcre-heavy` doesn't support this operation at all, so I guess `lens-regex-pcre` wins here :)\n\nHow can it possibly be **faster** if it's based on `pcre-heavy`? `lens-regex-pcre` only uses `pcre-heavy` for **finding** the matches, not substitution/replacement. After that it splits the text into chunks and traverses over them with whichever operation you've chosen. The nature of this implementation makes it a lot easier to understand than imperative implementations of the same thing. This means it's pretty easy to make edits, and is also the reason we can support arbitrary traversals/actions. It was easy enough, so I went ahead and made the whole thing use ByteString Builders, which sped it up a lot. I suspect that `pcre-heavy` can benefit from the same optimization if anyone feels like back-porting it; it could be (almost) as nicely using simple `traverse` without any lenses. The whole thing is only about 25 LOC.\n\nI'm neither a benchmarks nor stats person, so please open an issue if anything here seems fishy.\n\nWithout `pcre-light` and `pcre-heavy` this library wouldn't be possible, so huge thanks to all contributors!\n\nHere are the benchmarks on my 2013 Macbook (2.6 Ghz i5)\n\n```haskell\nbenchmarking static pattern search/pcre-heavy ... took 20.78 s, total 56 iterations\nbenchmarked static pattern search/pcre-heavy\ntime                 375.3 ms   (372.0 ms .. 378.5 ms)\n                     1.000 R²   (0.999 R² .. 1.000 R²)\nmean                 378.1 ms   (376.4 ms .. 380.8 ms)\nstd dev              3.747 ms   (922.3 μs .. 5.609 ms)\n\nbenchmarking static pattern search/lens-regex-pcre ... took 20.79 s, total 56 iterations\nbenchmarked static pattern search/lens-regex-pcre\ntime                 379.5 ms   (376.2 ms .. 382.4 ms)\n                     1.000 R²   (1.000 R² .. 1.000 R²)\nmean                 377.3 ms   (376.5 ms .. 378.4 ms)\nstd dev              1.667 ms   (1.075 ms .. 2.461 ms)\n\nbenchmarking complex pattern search/pcre-heavy ... took 95.95 s, total 56 iterations\nbenchmarked complex pattern search/pcre-heavy\ntime                 1.741 s    (1.737 s .. 1.746 s)\n                     1.000 R²   (1.000 R² .. 1.000 R²)\nmean                 1.746 s    (1.744 s .. 1.749 s)\nstd dev              4.499 ms   (3.186 ms .. 6.080 ms)\n\nbenchmarking complex pattern search/lens-regex-pcre ... took 97.26 s, total 56 iterations\nbenchmarked complex pattern search/lens-regex-pcre\ntime                 1.809 s    (1.736 s .. 1.908 s)\n                     0.996 R²   (0.991 R² .. 1.000 R²)\nmean                 1.757 s    (1.742 s .. 1.810 s)\nstd dev              42.83 ms   (11.51 ms .. 70.69 ms)\n\nbenchmarking simple replacement/pcre-heavy ... took 23.32 s, total 56 iterations\nbenchmarked simple replacement/pcre-heavy\ntime                 423.8 ms   (422.4 ms .. 425.3 ms)\n                     1.000 R²   (1.000 R² .. 1.000 R²)\nmean                 424.0 ms   (422.9 ms .. 426.2 ms)\nstd dev              2.684 ms   (1.239 ms .. 4.270 ms)\n\nbenchmarking simple replacement/lens-regex-pcre ... took 20.84 s, total 56 iterations\nbenchmarked simple replacement/lens-regex-pcre\ntime                 382.8 ms   (374.3 ms .. 391.5 ms)\n                     0.999 R²   (0.999 R² .. 1.000 R²)\nmean                 378.2 ms   (376.3 ms .. 381.0 ms)\nstd dev              3.794 ms   (2.577 ms .. 5.418 ms)\n\nbenchmarking complex replacement/pcre-heavy ... took 24.77 s, total 56 iterations\nbenchmarked complex replacement/pcre-heavy\ntime                 448.1 ms   (444.7 ms .. 450.0 ms)\n                     1.000 R²   (1.000 R² .. 1.000 R²)\nmean                 450.8 ms   (449.5 ms .. 453.9 ms)\nstd dev              3.129 ms   (947.0 μs .. 4.841 ms)\n\nbenchmarking complex replacement/lens-regex-pcre ... took 21.99 s, total 56 iterations\nbenchmarked complex replacement/lens-regex-pcre\ntime                 399.9 ms   (398.4 ms .. 402.2 ms)\n                     1.000 R²   (1.000 R² .. 1.000 R²)\nmean                 399.6 ms   (399.0 ms .. 400.4 ms)\nstd dev              1.135 ms   (826.2 μs .. 1.604 ms)\n\nBenchmark lens-regex-pcre-bench: FINISH\n```\n\n# Behaviour\n\nPrecise Expected behaviour (and examples) can be found in the test suites:\n\n* [ByteString tests](https://github.com/ChrisPenner/lens-regex-pcre/blob/master/test/ByteString.hs)\n* [Text tests](https://github.com/ChrisPenner/lens-regex-pcre/blob/master/test/Text.hs)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrispenner%2Flens-regex-pcre","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchrispenner%2Flens-regex-pcre","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrispenner%2Flens-regex-pcre/lists"}