我需要转换下一个php正则表达式:
/^ (?: \d{1,16} | (?: \x0A | \x0D | [\x20-\x5A] | \x5F | [\x61-\x7A] | \xC2\xA0 | \xCE\xA9 ){1,11} ) $/xsi
我是regex的新手,我找到了一个有用的链接:
http://www.regexplanet.com/advanced/java/index.html
我理解是否正确,我应该只粘贴php正则表达式,按“测试”,结果如下:
'/^ (?: \\d{1,16} | (?: \\x0A | \\x0D | [\\x20-\\x5A] | \\x5F | [\\x61-\\x7A] | \\xC2\\xA0 | \\xCE\\xA9 ){1,11} ) $/xsi'
会用Java吗?
答案 0 :(得分:3)
您的原始模式看起来很奇怪:用\x..
编写的大多数字符都在ASCII表中。为什么在为\n
,\x0A
\r
等编写(例如)\x0D
时使用此复杂表示法?它可以用更简单的方式编写(总是用于PHP):
/^(?:\d{1,16}|(?:\n|\r|[ -Z]|_|[a-z]|\xC2\xA0|\xCE\xA9){1,11})$/i
(我删除了x修饰符和非重要空格.s修饰符没用。)
由于模式不区分大小写(修饰符i),[a-z]
中已包含[ -Z]
(包含[A-Z]
,请参阅ASCII表)并且可以删除。另外,使用字符类而不是单个字符的替换是更短且更高效的:
/^(?:\d{1,16}|(?:[\n\r -Z_]|\xC2\xA0|\xCE\xA9){1,11})$/i
关于\xC2\xA0
和\xCE\xA9
:这些序列代表以UTF8编码的字符NO-BREAK SPACE
和GREEK CAPITAL LETTER OMEGA
。
PCRE(PHP正则表达式引擎)默认情况下不支持unicode,并将字符串读取为单字节序列(每个字符一个字节)。如果添加u
修饰符或者使用(*UTF8)
启动模式,则可以将字符串读取为UTF8编码的字符串。在您的模式中,没有u
修饰符,因此每个字节都被视为一个字符。
Java正则表达式引擎默认支持unicode,不会逐字节地逐字符地读取字符串。
为了简化从PHP到Java的“翻译”,我将使用u修饰符重写PHP模式:
/^(?:[0-9]{1,16}|[\n\r -Z_\x{00A0}\x{03A9}]{1,11})$/iu
描述每个字节的 \xC2\xA0
现在替换为\x{00A0}
,其中00A0
是字符NO-BREAK SPACE
的unicode代码点。欧米茄也是如此。 (请查看the unicode table)
请注意,u修饰符将\d
扩展为unicode表中的所有数字。为了防止这种副作用,我已将其替换为[0-9]
。
要编写Java模式,您只需要使用\x{....}
语法替换\u....
语法并使用CASE_INSENSITIVE选项:
^(?:[0-9]{1,16}|[\n\r -Z_\u00A0\u03A9]{1,11})$
(别忘了逃避反斜杠)