Re: Escape Meta Chars in Character Classes

Andreas Säger <[email protected]> Wed, 16 Dec 2015 16:51:12 +0100
Newsgroups gmane.comp.java.hsqldb.user
Message-ID <[email protected]>
Simplified and well working example:

CREATE MEMORY TABLE T ("PAIRS" CHAR(3));
INSERT INTO T VALUES('1,2');
INSERT INTO T VALUES('1\2');
INSERT INTO T VALUES('1+2');
INSERT INTO T VALUES('1/2');
INSERT INTO T VALUES('1.2');
INSERT INTO T VALUES('1:2');
INSERT INTO T VALUES('1;2');
INSERT INTO T VALUES('1-2');
INSERT INTO T VALUES('1&2');


SELECT REGEXP_SUBSTRING("PAIR",'\d[-+/&.:;]\d') FROM "T";

The regexp matches all records except the first and the second because
comma and backslash are not in the character class. It matches one
digit, followed by any record within character class [-+/&.:;], followed
by another digit. It works as expected without escaping special
characters because character classes are lists of literal characters.

But when you change the order of characters within the class, you get an
error

> java.util.regex.PatternSyntaxException: Illegal character range near index 10

when the last element of the character class is a metacharacter
according to
> http://docs.oracle.com/javase/tutorial/essential/regex/literals.html

> The metacharacters supported by this API are: <([{\^-=$!|]})?*+.>

or when the last character is a slash. May be there are even more "bad"
characters.

The following variants do raise the PatternSyntaxException and none of
the escape methods can fix it:
-- + at the end of class:
SELECT REGEXP_SUBSTRING("PAIR",'\d[-/&.:;+]\d') FROM "T";

-- . at the end of class:
SELECT REGEXP_SUBSTRING("PAIR",'\d[-/&:;+.]\d') FROM "T";

-- / at the end of class which is not even a metacharacter:
SELECT REGEXP_SUBSTRING("PAIR",'\d[-&:;+./]\d') FROM "T";

In other words: Certain characters need to be escaped when they are the
last element of a character class or you put a "good" character at the end.
Same as above but with last char escaped by \
-- \+ at the end of class:
SELECT REGEXP_SUBSTRING("PAIR",'\d[-/&.:;\+]\d') FROM "T";

-- \. at the end of class:
SELECT REGEXP_SUBSTRING("PAIR",'\d[-/&:;+\.]\d') FROM "T";

-- \/ at the end of class which is not even a metacharacter:
SELECT REGEXP_SUBSTRING("PAIR",'\d[-&:;+.\/]\d') FROM "T";

A backslash in a character class needs to be escaped by a leading
backslash in any case like the leading \\ in the following:
SELECT REGEXP_SUBSTRING("PAIR",'\d[\\-&:;+.\/]\d') FROM "T";


In my previous posting I wrote ...
> Same problem with an escaped slash \/ and with \Q/\E too ...


... which I can not reproduce anymore. Both escaping methods fix the
problem of "bad" char at the end of character classes.
After all, I think all this is somewhat "normal" but what is "normal" in
regexp context?



------------------------------------------------------------------------------