Request: (?(DEFINE)...)

Create issue
Issue #152 resolved
boolbag NA created an issue

Hi again Matthew,

This is the second in a series of posts to present a case for three features. In this post, I'll focus on (?(DEFINE)...)

When crafting long expressions with repeated components, I find the (?(DEFINE)...) syntax immensely valuable. It is the key to writing modular regex. Some time ago I presented an example to show the value of such a modular regex here.

(?(DEFINE)...) allows you to drop short names in the pattern. These names expand to large sub-expressions. When sub-expressions are repeated in multiple places in the pattern, this lets you keep your sanity, because you don't have to change the pattern in multiple places.

I came up with a workaround that I explained here some time ago. Nevertheless, for compatibility with PCRE and Perl when translating large expressions, it would be wonderful to have the same (?(DEFINE)...) syntax in regex.

Thanks in advance for considering it.

Comments (3)

  1. Matthew Barnett repo owner

    In your webpages you give a workaround for implementations that don't support it:

    (?:(?<foo>  )(?!))?
    

    There's a shorter alternative:

    (?=|(?<foo>  ))
    
  2. boolbag NA reporter

    Wow, that is awesome, thank you so much!!! And thank you also for the "shorter workaround tip" two posts up.

    I've already "advertised" the new features on the StackOverflow regex chat room, where many regex heads hang out. :)

    Will also go update my pages to mention that this is now supported. I've been meaning for some time to do a real tut on your engine (at the time I first mentioned it, I wasn't doing much Python.) Need to make the time for this.

    Here is a short example for anyone who would like to see the feature at work:

    import regex as mrab
    define_showcase = mrab.compile(r'''(?x)
                                    (?(DEFINE)
                                       (?<price>
                                       \$\d+\.\d{2}\b
                                       ) # end price def
                                    )
    
                                    (?&price)[-+](?&price)=(?&price)
                                    ''')
    print(define_showcase.search('total: $1.99+$2.99=$4.98'))
    
    // Output: <regex.Match object; span=(7, 24), match='$1.99+$2.99=$4.98'>
    
  3. Log in to comment