While the regex pattern isn't perfect at finding only the intended answer (there are a number of variations that the matching string will accept), I'll explain the code and build the answer that Ivo Beckers found.
First an explanation of regex calls that will be important. The pattern matcher moves through the input string, "consuming" characters as it matches them.
(?=__) is a positive lookahead which ensures the next characters match the specification in
__; however, unlike normal matching, a lookahead doesn't consume the characters, so they still need to be matched. Conversely, the negative lookahead
(?!__) looks ahead and ensures that the next characters don't match
(__) are used around matching statements like
__ (but not as part of a lookahead statement), it forms a "capturing group". This means that whatever
__ matches to will be stored as a subpattern that can be referred to later, and will be assigned a reference number based on the order of the opening bracket
(. For example, if I matched the string
abc against the pattern
. matches almost any single character), then it would match, and the stored subpatterns would be 1:
bc and 2:
c. Later in the pattern, we can match against these subpatterns
(?ix) sets modifiers, which change the behaviour of the pattern matching.
i means the pattern matching is case-insensitive. We then have a negative lookahead to check that the next two characters are not
[AD-ZC][a-jn-zjm]. This can be a
B followed by any character or any character followed by a
L. They can be non-alphabetical characters, but the next part sorts that out. Let's assume
BL so far.
This matches the first two letters to characters. Since it's on case-insensitive mode, this just makes sure that they're letters, but otherwise it would check that it's an uppercase and a lowercase letter. It also stores the pair as subpattern 1
bl and the first character of the two as subpattern 2
We perform a positive lookahead to check that the next character is a letter, followed by a negative lookahead to check that it's not
b-z (so it's
(.) then consumes that character and stores it as subpattern 3
This just matches
The next character is matched to a whitespace character
\s but not any of the special whitespace characters. This leaves us with a space '
' character stored as subpattern 4.
The three lookaheads assert that the next character is a letter, and not
. consumes the S, and
\3\2\2\3 matches those subpatterns in that order, which is
ABBA. This is followed by
h. The whole group is stored as subpattern 5
SABBATH, and the
h is stored as both subpatterns 6 and 7
This simply matches the numbered subpatterns and the
- character, giving
- SABBATH BL.
BLACK SABBATH - SABBATH BL
o and stores it as subpattern 8. It then matches
\8 and stores that, too, so subpatterns 8 and 9 are both
o. Then it matches
BLACK SABBATH - SABBATH BLOOD
Another negative lookahead to ensure that the next character isn't
[[:alpha:]] then matches the next alphabetical character, which is
y. We then add another space with
\4, giving us
BLACK SABBATH - SABBATH BLOODY.
* means to match
SABBATH) 0 or more times, as many times as possible. If we leave it as 0, we're already finished and have a matching pattern, or
BLACK SABBATH - SABBATH BLOODY SABBATHSABBATHSABBATHSABBATH is also valid. A quick Google search indicates that "Sabbath, Bloody Sabbath" is a real song, so
BLACK SABBATH - SABBATH BLOODY SABBATH seems to be the right answer. Alternatively, he may be listening to
zKack saZzatH - SazZATh ZkoOdY!