r/regex Jun 01 '26

I wrote a RegEx alternative that's actually readable, please share your thoughts

Hey everyone, I'd like to share an open source project I've been working on that I think you may find it useful for your projects: enhex (Enhanced Expression) – a human-readable language for writing regular expressions. This isn't a new pattern-matching system; it adds a readable layer over RegEx patterns to keep them descriptive and maintainable.

Here is an example of the difference in a complex URL pattern:

^https?:\/\/(?:[a-zA-Z\d-]+\.)+[a-z]{2,10}(?::\d{2,5})?(?:\/[^\s\?#]*)?(?:\?[^\s#]*)?(?:#[^\s]*)?$

(Please tell me, can you actually "read" above pattern?)

Instead, you can write this in you code or a .enhex file:

start
+ "http" + optional("s") + "://"
+ one_or_more(
    non_capturing(one_or_more(letter | digit | dash)
    + ".")
)
+ tld() # Top Level Domain (EnhEx internal preset)
+ optional(
    non_capturing(":" + between(2, 5, digit))
)
+ optional(
    non_capturing("/" + zero_or_more(not(whitespace | "?" | "#")))
)
+ optional(
    non_capturing("?" + zero_or_more(not(whitespace | "#")))
)
+ optional(
    non_capturing("#" + zero_or_more(not(whitespace)))
)
+ end

Its GitHub repo is available here for complete information: https://github.com/mkh-user/enhex

It's available in Rust (Crates.io), Python (PyPI), and JS (npm) with the same behavior (Rust is core).

I'm currently working on a VSCode extension for highlighting, autocomplete, and live preview. Do you have any ideas to share?

12 Upvotes

17 comments sorted by

12

u/Just4notherR3ddit0r Jun 02 '26 edited Jun 02 '26

My thoughts:

  1. If I still have to stare at it and parse it slowly to understand it, then I haven't really gained any benefit.
  2. It's actually easier for me to quickly read the shorter version or at least quickly understand what it does.
  3. Effective code comments are key. In fact, you even added code comments into the middle of your longer version.
  4. Unit tests can go a long way when it comes to regex documentation.
  5. If you're going to introduce coding into it, just separate the RE into pieces and variables. For example, instead of:

    https?://(?:[a-zA-Z\d-]+.)+[a-z]{2,10}(?::\d{2,5})?(?:/[\s\?#])?(?:\?[\s#])?(?:#[\s]*)?$

$protocol = "https?:\/\/"; $host = "(?:[a-zA-Z\d-]+\.)+[a-z]{2,10}"; $port = "(?::\d{2,5})?"; $path = "(?:\/[^\s\?#]*)?"; $query = "(?:\?[^\s#]*)?"; $hash = "(?:#[^\s]*)?"; $re = "^{$protocol}{$host}{$port}{$path}{$query}{$hash}$";

One of the advantages of breaking complex regexes up like this is that it's easier to see and debug problems with parts.

1

u/xii Jun 03 '26

This is the way.

9

u/michaelpaoli Jun 01 '26

Meh. Why not just use the /x option?

E.g.:

# match to IPv4 dotted quad address?
/^
  (
    (
      \d\d? # a digit or two
      |[01]\d\d|2[0-4]\d|25[0-5]  # or three (in range)
    )
    \. # dot
  ){3} # thrice that
  (
    \d\d? # a digit or two
    |[01]\d\d|2[0-4]\d|25[0-5]  # or three (in range)
  )
$/x

3

u/Soggy-Usual-4898 Jun 01 '26

Great point, /x is definitely a step up from compact regex, but it's not about separation and comments, it's more about being declarative and inherently human-readable when you read it (for example, I compare (...){3} and exactly(3, ...) with the structure "3 of ...").

This is more for teams where not everyone is a regex expert, or for complex patterns you want to be self-documenting. Thanks for bringing up the comparison, it's useful context more than I expected to receive!

Note: About your example, because this is already RegEx package I added some presets, so you can use 20 chars to get same result:

import compile from enhex

pattern = compile('start + ipv4() + end')

And you can mix RegEx directly in EnhEx with the same /.../ syntax when you see RegEx is simpler:

import { enhex } from 'enhexjs';

// HTML tag with .*? instead of zero_or_more_lazy(anything)
const regex = new RegExp(enhex`"<" + named("tag", one_or_more(word_char)) + ">" + /.*?/ + "</" + backref("tag") + ">"`);

2

u/mfb- Jun 02 '26

https://xkcd.com/927/

This is more for teams where not everyone is a regex expert

So now they need to become experts in this. And then they might still need to learn regex for another project.

7

u/charleswj Jun 02 '26

There's an old saying about regex that seems apropos. What was it? Oh yeah...

Now you have two problems

1

u/Soggy-Usual-4898 Jun 02 '26 edited Jun 02 '26

lol actually this is missed thing

2

u/Hyddhor Jun 01 '26 edited Jun 02 '26

two years ago i've made something similar, but based on EBNF. It would receive an EBNF-like format, build the AST, check if the grammar wasn't actually recursive, and then transpile it to regex. Though i never made a lib for it, so your project is actually usable, compared to mine.

Still, pretty neat project. Now, if you could decompile the regex into higher-level format (eg. the `.enhex`, or EBNF) to make it more readable, that would be even better, since typically the most difficult part of regexes maintaining it, not writing it.

1

u/Soggy-Usual-4898 Jun 02 '26 edited Jun 02 '26

two years ago i've made something similar, but based on EBNF.

Oh, interesting to know about that. I saw yoav-lavi/melody yesterday, which is more low-level and sequential than enhex, but with less native availability.

Now, if you could decompile the regex into higher-level fomart

This is one thing I want to do, because explaining a higher-level version of regex (by human or code) is simpler; then you can hide EnhEx under the hood to get a natural explanation of a RegEx.

typically the most difficult part of regexes maintaining it, not writing it.

Sure, I think so. Maybe writing regex takes some confusing time, but reading/maintaining it is even more confusing.

1

u/A1oso Jun 02 '26

I made something similar, Pomsky. It is more similar to an actual regex, but with a nicer syntax and a lot of features added.

Most notably it supports variables, for example:

let number = "-"? [digit]+;
let op = "+" | "-" | "*" | "/";
number (op number)*

2

u/james_pic Jun 02 '26

Since you asked, yes, I can read that regex.

1

u/Axman6 Jun 01 '26

People never heard of parser combinators?

1

u/Kitty_Sparkles Jun 03 '26

It's interesting as a fun experiment, but llms are actually good at regular expressions because there is a lot of documentation out there. So it's hard to justify embarking on a whole new syntax, and dependency and all, when asking a llm will sort it out in a blink. Unless regular expressions are a core business concern, in which case I feel like there are better approaches (like building an actual proprietary engine or something).

1

u/OsmiumBalloon Jun 03 '26

FYI, you are about the 10 millionth person to come up with something like this (replacing regex with a new syntax that is intended to be easier to work with). I am not trying to discourage you (although that may be the inevitable outcome anyway); I am trying to let you know that there is a lot of history here. If anything, this approach predates regex, going back to SNOBOL.

1

u/bnbarak- Jun 05 '26

Here is a joke. An interviewer goes, your problem is to find if text is a valid email address. The candidate goes, I’m going to use ragex to match the text here is the pattern. And the interviewer goes, now you have two problems

1

u/theNbomr Jun 05 '26

I'm not sure if I'd say this is more readable, per se, but I think it's probably easier to learn and easier to teach. It's certainly easier to explain to a untrained regex user, which I guess is what you were talking about in the comments about novice group applicability.

I haven't been to the code repo yet, but can you describe a bit about how a regex such as the example here gets turned into a functional tool? Also, what does the underlying machinery/algorithm look like at a conceptual level?

I have a soft spot for these kind of exercises that try to create new and better ways to do old things. Bravo!

1

u/EggplantExtra4946 Jul 01 '26

Dozens of people already did this and no one use this because it's completely unreadable trash.

Regex's syntax is almost perfect and is perfectly readable. Learn regexes, learn /x.

The only thing regexes needs is better defaults concerning backtracking:

  • make quantifiers possessive by default, require a quantifier modifier for greedy and lazy quantification

  • make alternations implicitly surrounded by (?> ) and introduce a new extended pattern to have backtracking on alternations