Java 使用正则表达式拆分字符串\w\w*\w+;?
我正在学习regexp,我想我已经开始掌握了。但是 我试图拆分一个字符串,我需要帮助来理解这样一个简单的事情:Java 使用正则表达式拆分字符串\w\w*\w+;?,java,regex,Java,Regex,我正在学习regexp,我想我已经开始掌握了。但是 我试图拆分一个字符串,我需要帮助来理解这样一个简单的事情: String input = "abcde"; System.out.println("[a-z] " + Arrays.toString(input.split("[a-z]"))); System.out.println("\\w " + Arrays.toString(input.split("\\w"))); System.out.println("\\w*? " + Arra
String input = "abcde";
System.out.println("[a-z] " + Arrays.toString(input.split("[a-z]")));
System.out.println("\\w " + Arrays.toString(input.split("\\w")));
System.out.println("\\w*? " + Arrays.toString(input.split("\\w*?")));
System.out.println("\\w+? " + Arrays.toString(input.split("\\w+?")));
The output is
[a-z] - []
\w - []
\w*? - [, a, b, c, d, e]
\w+? - []
为什么前两行中的任何一行都不拆分任何字符上的字符串?
第三个表达式\w*?,(问号防止贪婪)如我所料工作,在每个字符上拆分字符串。零个或多个匹配的星号返回空数组
我在记事本++和一个程序中尝试过该表达式,它显示了5个匹配项,如中所示:
Scanner ls = new Scanner(input);
while(ls.hasNext())
System.out.format("%s ", ls.findInLine("\\w");
Output is: a b c d e
这真的让我很困惑如果你用正则表达式分割一个字符串,你基本上就知道应该在哪里剪切字符串。这必然会删除与正则表达式匹配的内容。这意味着如果在
\w
处拆分,则每个字符都是拆分点,并且返回它们之间的子字符串(全部为空)。Java会自动删除尾随的空字符串,如中所述
这也解释了为什么惰性匹配\w*?
将为您提供每个字符,因为它将匹配任何字符(零宽度)之间(以及之前和之后)的每个位置。剩下的是字符串本身的字符
让我们把它分解一下:
[a-z]
,\w
,\w+?
a b c d e
└┘ └┘ └┘ └┘ └┘ └┘
你的绳子是
abcde
比赛内容如下:
a b c d e
└─┘└─┘└─┘└─┘└─┘
这会在匹配之间留下子字符串,所有子字符串都是空的
上述三个正则表达式在这方面的行为相同,因为它们都只匹配一个字符\w+?
将这样做,因为它缺少任何其他约束,这些约束可能会使+?
尝试匹配的不仅仅是简单的最小值(毕竟它是懒惰的)\w*?
a b c d e
└┘ └┘ └┘ └┘ └┘ └┘
在这种情况下,匹配在字符之间,留下以下子字符串:
"", "a", "b", "c", "d", "e", ""
不过,Java将后面的空文件扔掉了[a-z]
这样的模式,字符串都会在该匹配处剪切。由于字符串中的每个字符都与模式匹配,因此生成的数组为空(删除尾随的空字符串)
这同样适用于
\w
和\w+?
(一个或多个\w
,但重复次数尽可能少)。\w*?
产生了您所期望的结果,这是由于*?
量词可能会匹配零重复,因此为空字符串。在给定字符串的每个位置都会找到一个空字符串。让我们将这些调用分解为。关键是要从Java文档中注意到,“方法的工作方式就像使用给定的表达式和零的limit参数调用一样。因此,结果数组中不包括尾随的空字符串。”
这一个匹配每个字符(a、b、c、d、e),并且只在它们之间产生空字符串,这些字符串被省略
"abcde".split("\\w")); // => []
"abcde".split("\\w*?")); // => ["", "a", "b", "c", "d", "e"]
同样,字符串中的每个字符都是单词字符(\w
),因此结果是空字符串,这些字符串将被忽略
"abcde".split("\\w")); // => []
"abcde".split("\\w*?")); // => ["", "a", "b", "c", "d", "e"]
在这种情况下,*
表示“前面的项为零或多个”(\w
),它与空表达式匹配七次(一次在字符串开头,然后在每个字符之间匹配一次)。所以我们得到第一个空字符串,然后是每个字符
"abcde".split("\\w+?")); // => []
这里的+
表示“前面的一个或多个项”(\w
),它与整个输入字符串相匹配,只产生空字符串,该字符串被省略
使用
input.split(regex,-1)
再次尝试这些示例,您应该会看到所有的空字符串。我也想接受您的答案,谢谢您的帮助@肯尼特:当然,请考虑一下你认为有帮助的答案。我不敢相信你用java来分配ReGEX作业,而不是用不需要\\Dou\\O\\Uu \ BB\\\\\B\\A\\Acc\cc\\k\\\\\AA\\\\\\H\\HH\EE!!多痛苦啊!此外,您甚至不需要对正则表达式语法进行编译时检查,也不需要调试,等等。Java对这种工作不是很方便。您应该用一种更具同情心的语言开发正则表达式,然后将最终结果转换为Java。@tchrist您在考虑什么语言?除了sed和awk等shell工具外,Perl和Ruby还有一流的正则表达式,甚至Python也允许您跳过双反斜杠。Perl是唯一一个使用正则表达式调试器的调试器。Java的split
丢弃了后面的空字段,因为它模仿了Perl的split
,后者就是这样做的。在这两种语言中,您都可以通过向-1
的拆分添加另一个参数来抑制该行为。