空白匹配正则表达式 - Java

时间:2011-01-19 01:58:47

标签: java regex whitespace

regular expressions的Java API声明\s将匹配空格。所以正则表达式\\s\\s应匹配两个空格。

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

这样做的目的是用一个空格替换两个连续空格的所有实例。然而,这实际上并不起作用。

我对正则表达式或“空白”一词有严重的误解吗?

9 个答案:

答案 0 :(得分:173)

您无法在Java中使用\s来匹配其自己的本机字符集上的空白区域,因为Java不支持Unicode空白属性 - 即使严格要求满足{{3它所拥有的不是符合标准的,唉。

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

白色空间是一个相当稳定的属性,而那些相同的空间几乎永远存在。即便如此,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 + "]";

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


=begin soapbox

抱歉'回合所有这一切。 Java的正则表达不能在自己的原生字符集上运行得很好,,所以你真的必须跳过异国情调的箍来使它们工作。

如果您认为空白区域不好,您应该看看为了让\w\b最终表现得正常而必须做些什么!

是的,这是可能的,是的,这是一个令人头疼的混乱。这甚至是慈善事业。为Java提供符合标准的正则表达式库的最简单方法是将JNI转换为ICU的东西。这就是谷歌为Android所做的事情,因为OraSun并不适合。

如果您不想这样做但仍想坚持使用Java,我有一个前端正则表达式重写库,我编写了“修复”Java的模式,至少是为了使它们符合{{的要求3}}

=end soapbox

答案 1 :(得分:42)

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

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

答案 2 :(得分:12)

对于Java(不是php,不是javascript,而不是任何其他):

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

答案 3 :(得分:5)

当我向Regexbuddy(正则表达式开发人员应用程序)论坛发出问题时,我得到了更准确的回复我的Java问题:

"留言作者:Jan Goyvaerts

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

如果输入仅为ASCII,则

... \ s \ s将匹配两个空格。真正的问题在于OP的代码,正如该问题中接受的答案所指出的那样。"

答案 4 :(得分:4)

似乎对我有用:

String s = "  a   b      c";
System.out.println("\""  + s.replaceAll("\\s\\s", " ") + "\"");

将打印:

" a  b   c"

我认为您打算这样做而不是代码:

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

System.out.println(result);

答案 5 :(得分:1)

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;
 }
}

答案 6 :(得分:1)

为了您的目的,您可以使用此snnippet:

import org.apache.commons.lang3.StringUtils;
StrintUtils.StringUtils.normalizeSpace(string);

这会将间距规范化为单一,并且也会剥离起始和尾随空格。

为了您的目的,您可以使用此snnippet:

import org.apache.commons.lang3.StringUtils;
StrintUtils.StringUtils.normalizeSpace(string);

这会将间距规范化为单一,并且也会剥离起始和尾随空格。

String sampleString =" Hello world!&#34 ;; sampleString.replaceAll(" \ s {2}",""); //恰好替换两个连续的空格

sampleString.replaceAll(" \ s {2,}",""); //替换两个或多个连续的空格

答案 7 :(得分:0)

自从首次提出此问题以来,Java就已经发展起来。您可以使用\p{Zs}组来匹配所有方式的Unicode空格字符。

因此,如果您想用一个普通空间替换一个或多个奇异空间,则可以这样做:

String txt = "whatever my string is";
txt.replaceAll("\\p{Zs}+", " ")

还应该知道,如果您使用过trim()字符串函数,则应查看一下(相对较新的)strip()stripLeading()stripTrailing()函数在弦上。可以帮助您剪裁各种松散的空白字符。有关包含什么空间的更多信息,请参见Java的Character.isWhitespace()函数。

答案 8 :(得分:-3)

在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 = " a    b      cdef     gh  ij   kl";
            System.out.println ("Initial: \"" + tester + "\"");
            System.out.println ("Two21WS: \"" + new Two21WS(tester) + "\"");
}}

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

%java Two21WS 首字母:“a b cdef gh ij kl” Two21WS:“a b cdef gh ij kl”