空白匹配正则expression式 – Java

正则expression式的Java API声明\s将匹配空格。 所以正则expression式应该匹配两个空格。

 Pattern whitespace = Pattern.compile("\\s\\s"); matcher = whitespace.matcher(modLine); while (matcher.find()) matcher.replaceAll(" "); 

这样做的目的是用一个空格replace连续两个空格的所有实例。 但是这并不实际工作。

我对正则expression式还是“空白”一词有严重的误解?

是的,你需要获取matcher.replaceAll()的结果:

 String result = matcher.replaceAll(" "); System.out.println(result); 

您不能在Java中使用\s来匹配自己的本地字符集上的空白区域,因为Java不支持Unicode空白属性 – 即使这样做是严格要求符合UTS#18的RL1.2! 它所做的不符合标准,唉。

Unicode定义26个代码点为\p{White_Space} :其中20个是\pZ GeneralCategory = Separator ,其余6个是\p{Cc} GeneralCategory = Control

白色空间是一个相当稳定的财产,而那些相同的空间几乎是永远的。 即使如此,Java没有符合Unicode标准的属性,所以你必须使用这样的代码:

 String whitespace_chars = "" /* dummy empty string for homogeneity */ + "\\u0009" // CHARACTER TABULATION + "\\u000A" // LINE FEED (LF) + "\\u000B" // LINE TABULATION + "\\u000C" // FORM FEED (FF) + "\\u000D" // CARRIAGE RETURN (CR) + "\\u0020" // SPACE + "\\u0085" // NEXT LINE (NEL) + "\\u00A0" // NO-BREAK SPACE + "\\u1680" // OGHAM SPACE MARK + "\\u180E" // MONGOLIAN VOWEL SEPARATOR + "\\u2000" // EN QUAD + "\\u2001" // EM QUAD + "\\u2002" // EN SPACE + "\\u2003" // EM SPACE + "\\u2004" // THREE-PER-EM SPACE + "\\u2005" // FOUR-PER-EM SPACE + "\\u2006" // SIX-PER-EM SPACE + "\\u2007" // FIGURE SPACE + "\\u2008" // PUNCTUATION SPACE + "\\u2009" // THIN SPACE + "\\u200A" // HAIR SPACE + "\\u2028" // LINE SEPARATOR + "\\u2029" // PARAGRAPH SEPARATOR + "\\u202F" // NARROW NO-BREAK SPACE + "\\u205F" // MEDIUM MATHEMATICAL SPACE + "\\u3000" // IDEOGRAPHIC SPACE ; /* A \s that actually works for Java's native character set: Unicode */ String whitespace_charclass = "[" + whitespace_chars + "]"; /* A \S that actually works for Java's native character set: Unicode */ String not_whitespace_charclass = "[^" + whitespace_chars + "]"; 

现在你可以在你的replaceAll使用whitespace_charclass + "+"作为模式。


=begin soapbox

对不起,“所有这一切。 Java的正则expression式在它自己的本地字符集上工作得不太好,所以你真的必须跳过异乎寻常的箍来使它们工作。

如果你认为空白是不好的,你应该看看你必须做些什么才能使\w\b最终performance正常!

是的,这是可能的,是的,这是一个麻木的混乱。 这是慈善,甚至。 获得一个符合标准的Java正则expression式库最简单的方法是将JNI转换为ICU的东西。 这就是Google为Android所做的,因为OraSun没有达到要求。

如果你不想这样做,但仍然想要坚持使用Java,我有一个前端正则expression式重写库,我写了“修复”了Java的模式,至less让它们符合UTS中RL1.2a的要求#18, Unicode正则expression式

=end soapbox

似乎为我工作:

 String s = " abc"; System.out.println("\"" + s.replaceAll("\\s\\s", " ") + "\""); 

将打印:

 " abc" 

我想你打算这样做,而不是你的代码:

 Pattern whitespace = Pattern.compile("\\s\\s"); Matcher matcher = whitespace.matcher(s); String result = ""; if (matcher.find()) { result = matcher.replaceAll(" "); } System.out.println(result); 

对于Java(不是PHP,不是JavaScript,不是其他):

 txt.replaceAll("\\p{javaSpaceChar}{2,}"," ") 

当我向Regexbuddy(正则expression式开发者应用程序)论坛发送一个问题时,我更加确切地回答了我的Java问题:

“消息作者:Jan Goyvaerts

在Java中,shorthands \ s,\ d和\ w只包含ASCII字符。 …这不是Java中的错误,而只是使用正则expression式时需要注意的许多事情之一。 要匹配所有Unicode空白以及换行符,可以在Java中使用[\ s \ p {Z}]。 RegexBuddy还不支持特定于Java的属性,例如\ p {javaSpaceChar}(它与[\ s \ p {Z}]完全相同的字符)。

如果input仅为ASCII,则\ s \ s将匹配两个空格。 真正的问题在于OP的代码,正如在这个问题上被接受的答案所指出的那样。“

 Pattern whitespace = Pattern.compile("\\s\\s"); matcher = whitespace.matcher(modLine); boolean flag = true; while(flag) { //Update your original search text with the result of the replace modLine = matcher.replaceAll(" "); //reset matcher to look at this "new" text matcher = whitespace.matcher(modLine); //search again ... and if no match , set flag to false to exit, else run again if(!matcher.find()) { flag = false; } } 

在RE中使用空白是一个痛苦,但我相信他们的工作。 OP的问题也可以使用StringTokenizer或split()方法来解决。 然而,要使用RE(取消注释println()来查看匹配器是如何分解string的),下面是一个示例代码:

 import java.util.regex.*; public class Two21WS { private String str = ""; private Pattern pattern = Pattern.compile ("\\s{2,}"); // multiple spaces public Two21WS (String s) { StringBuffer sb = new StringBuffer(); Matcher matcher = pattern.matcher (s); int startNext = 0; while (matcher.find (startNext)) { if (startNext == 0) sb.append (s.substring (0, matcher.start())); else sb.append (s.substring (startNext, matcher.start())); sb.append (" "); startNext = matcher.end(); //System.out.println ("Start, end = " + matcher.start()+", "+matcher.end() + // ", sb: \"" + sb.toString() + "\""); } sb.append (s.substring (startNext)); str = sb.toString(); } public String toString () { return str; } public static void main (String[] args) { String tester = " ab cdef gh ij kl"; System.out.println ("Initial: \"" + tester + "\""); System.out.println ("Two21WS: \"" + new Two21WS(tester) + "\""); }} 

它产生以下内容(使用javac编译并在命令提示符下运行):

%java Two21WS Initial:“ab cdef gh ij kl”Two21WS:“ab cdef gh ij kl”