(!a){0}是什么意思?在Java正则表达式中是什么意思?
受此启发,我开始使用一些包含(!a){0}是什么意思?在Java正则表达式中是什么意思?,java,android,regex,split,Java,Android,Regex,Split,受此启发,我开始使用一些包含{0}量词的正则表达式,并编写了一个小型java程序,该程序基于各种测试正则表达式拆分测试短语: private static final String TEST_STR = "Just a test-phrase!! 1.2.3.. @ {(t·e·s·t)}"; private static void test(final String pattern) { System.out.format("%-17s", "\"" + pattern +
{0}
量词的正则表达式,并编写了一个小型java程序,该程序基于各种测试正则表达式拆分测试短语:
private static final String TEST_STR =
"Just a test-phrase!! 1.2.3.. @ {(t·e·s·t)}";
private static void test(final String pattern) {
System.out.format("%-17s", "\"" + pattern + "\":");
System.out.println(Arrays.toString(TEST_STR.split(pattern)));
}
public static void main(String[] args) {
test("");
test("{0}");
test(".{0}");
test("([^.]{0})?+");
test("(?!a){0}");
test("(?!a).{0}");
test("(?!.{0}).{0}");
test(".{0}(?<!a)");
test(".{0}(?<!.{0})");
}
为什么Android中的正则表达式的行为不同于普通Java?我研究了oracles Java 1.7的源代码
“{0}”
我发现一些代码在主循环中找到?、*或+时抛出“悬空元字符”。也就是说,不能紧跟在某个文本、组、“
或明确检查量词的任何其他地方之后。出于某种原因,{
不在该列表中。结果是它通过了所有特殊字符检查,并开始解析文本字符串。它遇到的第一个字符是{
,它告诉解析器是时候停止解析文本字符串并检查量词了
结果是,“{n}”
将匹配空字符串n次
另一个结果是第二个“x{m}{n}”
将首先匹配x
m
次,然后匹配空字符串n
次,有效地忽略{n}
,正如@Kobi在上面的评论中提到的那样
对我来说似乎是个bug,但如果他们想保留它以实现向后兼容性,我也不会感到惊讶
“(?!a){0}”
“(?!a)”
只是一个可量化的节点。您可以检查下一个字符是否为“a”10次。但每次都会返回相同的结果,因此这不是很有用。在我们的示例中,它将检查下一个字符是否为“a”0次,这将始终成功
请注意,作为一种优化,当匹配的长度为0(如此处)时,量词从不贪婪。这也防止了“(?!a)*”
情况下的无限递归
“(?!a)。{0}”和“{0}(?仅供参考,你可以在这里测试java:哈哈,我甚至不知道这个网站:-)@martincarneye还有这个问题-如果你不介意的话,我直接链接到我的答案,因为我认为它是相关的。基本上,java忽略了冗余的{n}
,这在大多数其他正则表达式中是非法的(如您发布的示例中所示)。这与代码高尔夫无关。这是关于对java正则表达式引擎如何工作的深入理解。Android与java之间有些不同并不奇怪,尤其是像这样的情况,因为Android java是java的重新实现,就像Linux是Unix的重新实现,但无法直接访问源代码一样。Android使用ICU正则表达式,它与Java相似,但在支持的结构方面与Java不同。引擎如何解释量词并不重要。底线是,量词/重复运算符在不量化任何内容的情况下不能存在于状态机中。而且,它们不能被解释为独立状态。伊森,{不在该列表中
-你是说没有解析有效的范围量词吗?那不是真的。{5}
在某个地方被解析为重复运算符,否则它是一个文本。没有有效的前导值,就没有有效的量词解释。因此,x{3}{8}
被解析为嵌套的量词,它没有任何意义。这也防止了“(?!a)*”情况下的无限递归。
断言上的所有量词都解析为1或0。与非贪婪循环或无限循环无关。这可以用基准测试。Regex1:(?!a){400000100000000}完成的迭代:每次迭代发现的50/50(x 1000)个匹配:2个运行时间:0.26秒、256.39毫秒、256387微秒正则表达式2:(?!a)+完成的迭代:每次迭代发现的50/50(x 1000)个匹配:2个运行时间:0.25秒、254.53毫秒、254529微秒(?!a){400000100000000}已完成迭代:每次迭代找到50/50(x 1000)个匹配项:2个经过时间:0.25秒、254.34毫秒、254339µs Regex2:(?!a){1}已完成迭代:50/50(x 1000)每次迭代找到的匹配项:2个经过的时间:0.25秒、254.06毫秒、254059微秒
,所以贪婪/非贪婪与此无关。@sln量词不能在状态机中存在,如果它们不量化任何东西
。正是如此。这就是为什么在主循环中,当没有什么可量化时,代码抛出“挂起元字符。例如,使用regex“+”
。只有{
字符漏掉,这似乎是一个错误。当Java解析可以量化的字符时,它将检查{
,并正常工作。
"": [, J, u, s, t, , a, , t, e, s, t, -, p, h, r, a, s, e, !, !, , 1, ., 2, ., 3, ., ., , @, , {, (, t, ·, e, ·, s, ·, t, ), }]
"{0}": [, J, u, s, t, , a, , t, e, s, t, -, p, h, r, a, s, e, !, !, , 1, ., 2, ., 3, ., ., , @, , {, (, t, ·, e, ·, s, ·, t, ), }]
".{0}": [, J, u, s, t, , a, , t, e, s, t, -, p, h, r, a, s, e, !, !, , 1, ., 2, ., 3, ., ., , @, , {, (, t, ·, e, ·, s, ·, t, ), }]
"([^.]{0})?+": [, J, u, s, t, , a, , t, e, s, t, -, p, h, r, a, s, e, !, !, , 1, ., 2, ., 3, ., ., , @, , {, (, t, ·, e, ·, s, ·, t, ), }]
"(?!a){0}": [, J, u, s, t, , a, , t, e, s, t, -, p, h, r, a, s, e, !, !, , 1, ., 2, ., 3, ., ., , @, , {, (, t, ·, e, ·, s, ·, t, ), }]
"(?!a).{0}": [, J, u, s, t, a, , t, e, s, t, -, p, h, ra, s, e, !, !, , 1, ., 2, ., 3, ., ., , @, , {, (, t, ·, e, ·, s, ·, t, ), }]
"(?!.{0}).{0}": [Just a test-phrase!! 1.2.3.. @ {(t·e·s·t)}]
".{0}(?<!a)": [, J, u, s, t, , a , t, e, s, t, -, p, h, r, as, e, !, !, , 1, ., 2, ., 3, ., ., , @, , {, (, t, ·, e, ·, s, ·, t, ), }]
".{0}(?<!.{0})": [Just a test-phrase!! 1.2.3.. @ {(t·e·s·t)}]
03-20 22:43:31.941: D/AndroidRuntime(2799): Shutting down VM
03-20 22:43:31.950: E/AndroidRuntime(2799): FATAL EXCEPTION: main
03-20 22:43:31.950: E/AndroidRuntime(2799): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.appham.courseraapp1/com.appham.courseraapp1.MainActivity}: java.util.regex.PatternSyntaxException: Syntax error in regexp pattern near index 6:
03-20 22:43:31.950: E/AndroidRuntime(2799): (?!a){0}
03-20 22:43:31.950: E/AndroidRuntime(2799): ^
03-20 22:43:31.950: E/AndroidRuntime(2799): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
03-20 22:43:31.950: E/AndroidRuntime(2799): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
03-20 22:43:31.950: E/AndroidRuntime(2799): at android.app.ActivityThread.access$600(ActivityThread.java:141)
03-20 22:43:31.950: E/AndroidRuntime(2799): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
03-20 22:43:31.950: E/AndroidRuntime(2799): at android.os.Handler.dispatchMessage(Handler.java:99)
03-20 22:43:31.950: E/AndroidRuntime(2799): at android.os.Looper.loop(Looper.java:137)
03-20 22:43:31.950: E/AndroidRuntime(2799): at android.app.ActivityThread.main(ActivityThread.java:5041)
03-20 22:43:31.950: E/AndroidRuntime(2799): at java.lang.reflect.Method.invokeNative(Native Method)
03-20 22:43:31.950: E/AndroidRuntime(2799): at java.lang.reflect.Method.invoke(Method.java:511)
03-20 22:43:31.950: E/AndroidRuntime(2799): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
03-20 22:43:31.950: E/AndroidRuntime(2799): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
03-20 22:43:31.950: E/AndroidRuntime(2799): at dalvik.system.NativeStart.main(Native Method)
03-20 22:43:31.950: E/AndroidRuntime(2799): Caused by: java.util.regex.PatternSyntaxException: Syntax error in regexp pattern near index 6:
03-20 22:43:31.950: E/AndroidRuntime(2799): (?!a){0}
03-20 22:43:31.950: E/AndroidRuntime(2799): ^
03-20 22:43:31.950: E/AndroidRuntime(2799): at java.util.regex.Pattern.compileImpl(Native Method)
03-20 22:43:31.950: E/AndroidRuntime(2799): at java.util.regex.Pattern.compile(Pattern.java:407)
03-20 22:43:31.950: E/AndroidRuntime(2799): at java.util.regex.Pattern.<init>(Pattern.java:390)
03-20 22:43:31.950: E/AndroidRuntime(2799): at java.util.regex.Pattern.compile(Pattern.java:381)
03-20 22:43:31.950: E/AndroidRuntime(2799): at java.lang.String.split(String.java:1832)
03-20 22:43:31.950: E/AndroidRuntime(2799): at java.lang.String.split(String.java:1813)
03-20 22:43:31.950: E/AndroidRuntime(2799): at com.appham.courseraapp1.MainActivity.onCreate(MainActivity.java:22)
03-20 22:43:31.950: E/AndroidRuntime(2799): at android.app.Activity.performCreate(Activity.java:5104)
03-20 22:43:31.950: E/AndroidRuntime(2799): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
03-20 22:43:31.950: E/AndroidRuntime(2799): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
03-20 22:43:31.950: E/AndroidRuntime(2799): ... 11 more