Know your regex flavours
There are a surprising amount of people who think that regular expressions are essentially language agnostic. However, there are actually quite substantial differences between flavours, and especially for code golf it's good to know a few of them, and their interesting features, so you can pick the best for each task. Here is an overview over several important flavours and what sets them apart from others. (This list can't really be complete, but let me know if I missed something really glaring.)
Perl and PCRE
I'm throwing these into a single pot, as I'm not too familiar with the Perl flavour and they're mostly equivalent (PCRE is for Perl-Compatible Regular Expressions after all). The main advantage of the Perl flavour is that you can actually call Perl code from inside the regex and substitution.
- Recursion/subroutines. Probably the most important feature for golfing (which only exists in a couple of flavours).
- Conditional patterns
(?(group)yes|no)
.
- Supports change of case in the replacement string with
\l
, \u
, \L
and \U
.
- PCRE allows alternation in lookbehinds, where each alternative can have a different (but fixed) length. (Most flavours, including Perl require lookbehinds to have an overall fixed length.)
\G
to anchor a match to the end of the previous match.
\K
to reset the beginning of the match
- PCRE supports both Unicode character properties and scripts.
\Q...\E
to escape longer runs of characters. Useful when you're trying to match a string that contains many meta-characters.
.NET
This is probably the most powerful flavour, with only very few shortcomings.
One important shortcoming in terms of golfing is that it doesn't support possessive quantifiers like some other flavours. Instead of .?+
you'll have to write (?>.?)
.
Java
- Due to a bug (see Appendix) Java supports a limited type of variable-length lookbehind: you can lookbehind all the way to the beginning of the string with
.*
from where you can now start a lookahead, like (?<=(?=lookahead).*)
.
- Supports union and intersection of character classes.
- Has the most extensive support for Unicode, with character classes for "Unicode scripts, blocks, categories and binary properties".
\Q...\E
as in Perl/PCRE.
Ruby
In recent versions, this flavour is similarly powerful as PCRE, including the support for subroutine calls. Like Java, it also supports union and intersection of character classes. One special feature is the built-in character class for hex digits: \h
(and the negated \H
).
The most useful feature for golfing though is how Ruby handles quantifiers. Most notably, it's possible to nest quantifiers without parentheses. .{5,7}+
works and so does .{3}?
. Also, as opposed to most other flavours, if the lower bound on a quantifier is 0
it can be omitted, e.g. .{,5}
is equivalent to .{0,5}
.
As for subroutines, the major difference between PCRE's subroutines and Ruby's subroutines, is that Ruby's syntax is a byte longer (?n)
vs \g<n>
, but Ruby's subroutines can be used for capturing, whereas PCRE resets captures after a subroutine finishes.
Finally, Ruby has different semantics for line-related modifiers than most other flavours. The modifier that's usually called m
in other flavours is always on in Ruby. So ^
and $
always match the beginning and end of a line not just the beginning and end of the string. This can save you a byte if you need this behaviour, but it will cost you extra bytes if you don't, because you'll have to replace ^
and $
with \A
and \z
, respectively. In addition to that, the modifier that is usually called s
(which makes .
match linefeeds) is called m
in Ruby instead. This doesn't affect byte counts, but should be kept in mind to avoid confusion.
Python
Python has a solid flavour, but I'm not aware of any particularly useful features that you wouldn't find anywhere else.
However, there is the regex module, which is intended to replace the re
module at some point, and which contains a lot of interesting features. In addition to adding support for recursion, variable-length lookbehinds and character class combination operators, it also has the unique feature of fuzzy matching. In essence you can specify a number of errors (insertions, deletions, substitutions) which are allowed, and the engine will also give you approximate matches.
ECMAScript
The ECMAScript flavour is very limited, and hence rarely very useful for golfing. The only thing it's got going for it is the negated empty character class [^]
to match any character as well as the unconditionally failing empty character class []
(as opposed to the usual (?!)
). Unfortunately, the flavour does not have any features which makes the latter useful for normal problems.
Lua
Lua has its own fairly unique flavour, which is quite limited (e.g. you can't even quantify groups) but does come with a handful of useful and interesting features.
- It's got a large number of shorthands for built-in character classes, including punctuation, upper/lower case characters and hex digits.
- With
%b
it supports a very compact syntax to match balanced strings. E.g. %b()
matches a (
and then everything up to a matching )
(correctly skipping inner matched pairs). (
and )
can be any two characters here.
Boost
Boost's regex flavour is essentially Perl's. However, it has some nice new features for regex substitution, including case changes and conditionals. The latter is unique to Boost as far as I'm aware.