News for hackers. Stuff that matters.
Re:The Greatest Regex Trick Ever (2014) by to3m on Saturday September 26, 2015 @09:04AM (#10282989)
Another way of doing it is to use variables and helper functions, particularly if you're going to be creating lots of regexps from similar components. This is what I usually do in Python. For example, while making no promises about the value of this code specifically:

    def any(x): return x+"*"
    def many(x): return x+"+"
    def capture(x): return "("+x+")"
    def lit(x): return re.escape(x) # shorthand
    bol="^"; eol="$"
    ident="[A-Za-z_][A-Za-z0-9_]*";
    
    find_function=(bol+any(" ")+lit("def")+many(" ")+
                   capture(ident)+any(" ")+lit(":")+
                   any(" ")+eol)
You can handle more or less stuff this way according to how much you and/or your readers like regexp syntaxp. The above is probably further than I'd take it in practice; I'm familiar with the regular expression syntax, but I'd still probably at least use something like the `ident' variable just to keep clutter out of the regexp.

(A nice demonstration of this sort of thing is emacs's rx module (see, e.g., http://emacswiki.org/emacs/rx). I couldn't find any good non-emacs documentation about this, nor much that would make sense to people unfamiliar with lisp, but when you're in emacs you can get help on it using C-h f rx RET.)

Re:The Greatest Regex Trick Ever (2014) by TeMPOraL on Saturday September 26, 2015 @09:43AM (#10283077)
I agree. In terms of variables, I think a good strategy is assigning names to meanings, e.g.

    PRODUCT_ID = "[0-9]{2}[A-Z]{1,5}"
    ...
    CUSTOMER_ID = "[0-9]{2}[A-Z]{1,5}"
    ...
    ...
    regexp = "(" + PRODUCT_ID + ")" // capture product ID in group 1
           + "something something"  // something something
           + "(" + CUSTOMER_ID + ")"; // capture customer ID in group 2
In this example, even though the two constants contain the same regular expresison, they refer to two different concepts. Part of the problem with understanding regexp-based code is connecting parts of the expression with what they mean. Above strategy addresses this.

I also like assigning names to capture groups I depend on. So instead of, later in code, asking for e.g. matcher.group(2), I ask for matcher.group(GROUP_CUSTOMER_ID). Makes for a much more readable code.

Speaking of Emacs's rx, it's absolutely amazing and I'm sad that I only discovered it just few days ago :(. Another similar concept, from the other side of "code = data" equality is Common Lisp's (of course it's Lisp again) CL-PPCRE and its internal representation of regular expressions:

    * (parse-string "(ab)*")
    (:GREEDY-REPETITION 0 NIL (:REGISTER "ab"))
    
    * (parse-string "(a(b))")
    (:REGISTER (:SEQUENCE #\a (:REGISTER #\b)))
    
    * (parse-string "(?:abc){3,5}")
    (:GREEDY-REPETITION 3 5 (:GROUP "abc"))
You can encode any regexp you want as an S-expression, trading off conciseness for legibility. See http://weitz.de/cl-ppcre/#create-scanner2 for more.