空格匹配Regex-Java

空格匹配Regex-Java,java,regex,whitespace,Java,Regex,Whitespace,\s状态的Java API将匹配空白。因此正则表达式\\s\\s应该匹配两个空格 Pattern whitespace = Pattern.compile("\\s\\s"); matcher = whitespace.matcher(modLine); while (matcher.find()) matcher.replaceAll(" "); 这样做的目的是用一个空格替换两个连续空格的所有实例。然而,这实际上并不起作用 我是否对正则表达式或“空白”一词有严重误解?似乎适合我: Strin

\s
状态的Java API将匹配空白。因此正则表达式
\\s\\s
应该匹配两个空格

Pattern whitespace = Pattern.compile("\\s\\s");
matcher = whitespace.matcher(modLine);
while (matcher.find()) matcher.replaceAll(" ");
这样做的目的是用一个空格替换两个连续空格的所有实例。然而,这实际上并不起作用

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

似乎适合我:

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

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


您不能在Java中使用
\s
来匹配其本机字符集上的空白,因为Java不支持Unicode空白属性——尽管严格要求这样做是为了满足它所具有的不符合标准的要求,唉

Unicode将26个代码点定义为
\p{White_Space}
:其中20个是各种
\pZ
GeneralCategory=分隔符,其余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\u charclass++“
作为
replaceAll
中的模式


对不起,这一切Java的正则表达式在它自己的本地字符集上不能很好地工作,,所以你真的必须跳出异国情调才能让它们工作

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

是的,这是可能的,是的,这是一个令人麻木的混乱。这甚至是慈善行为。要获得Java的标准配置正则表达式库,最简单的方法是将JNI转移到ICU的东西上。这就是谷歌为Android所做的,因为OraSun的不符合标准


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

在RE中使用空格是一种痛苦,但我相信它们是有效的。OP的问题也可以使用StringTokenizer或split()方法解决。但是,要使用RE(取消对println()的注释以查看匹配器如何分解字符串),下面是一个示例代码:

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”

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


当我向Regexbuddy(regex开发者应用程序)论坛发送问题时,我得到了对我的Java问题更准确的回答:

“消息作者:Jan Goyvaerts

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


…\s\s将匹配两个空格,如果输入仅为ASCII。真正的问题是OP的代码,正如该问题中公认的答案所指出的那样。”

出于您的目的,您可以使用此snippet:

import org.apache.commons.lang3.StringUtils;

StringUtils.normalizeSpace(string);
这将使间距标准化为单个,并将删除起始和尾随空格

String sampleString = "Hello    world!";
sampleString.replaceAll("\\s{2}", " "); // replaces exactly two consecutive spaces
sampleString.replaceAll("\\s{2,}", " "); // replaces two or more consecutive white spaces

自从这个问题第一次被提出以来,Java就一直在发展。通过使用
\p{Zs}
组,可以匹配所有形式的unicode空格字符

因此,如果要将一个或多个奇异空间替换为普通空间,可以执行以下操作:

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

同样值得一提的是,如果您使用了
trim()
string函数,那么您应该看看字符串上的(相对较新的)
strip()
stripLeading()
stripTraining()
函数。可以帮助您删除各种松鼠般的空白字符。有关包含哪些空格的更多信息,请参阅Java的
Character.isWhitespace()
函数

String有一个replaceAll函数,可以为您节省几行代码。这不是你的误解,而是Java的误解。尝试拆分字符串,如“abc\xA0 def\x85 xyz”以了解我的意思:这里只有三个字段。是否尝试了“\\s+”。这样可以将两个或多个空格替换为一个。我已经想了一个多小时了,为什么我的\\s split没有拆分为空格。万分感谢!嘎。我觉得自己是世界上最大的白痴。我和另外两个人似乎都没有注意到这一点。我想最愚蠢的小错误有时会让我们失望,是吗?真的!我猜这会发生在最好的情况下如果文本有空格,我需要得到什么?根据我下面的回答,如果要匹配unicode空格,请使用\p{Zs}而不是\s。WTF!?既然可以调用
replaceAll()
,为什么还要这么做呢?感谢大家对Java的正则表达式限制的关注+1我投票认为这个答案很有帮助,并发现我已经有了答案。所以第二次谢谢你:)这真是太老了。在java7中使用UNICODE_CHARACTER_类标志修复了这个问题,对吗?(或使用(?U))@tchrist如果这在java 7+中已修复,您是否可以使用现在正确的方法更新答案?在java 7+中,您可以执行:“(?U)\s”来运行符合Unicode技术标准的正则表达式。或者,您可以在创建模式时使UNICODE_CHARACTER_类标志为true。医生:迈克,虽然我感谢你抽出时间来回答,但这个问题已经在几个月前解决了。没有必要回答像这样古老的问题。如果有人能展示不同的答案,b
import org.apache.commons.lang3.StringUtils;

StringUtils.normalizeSpace(string);
String sampleString = "Hello    world!";
sampleString.replaceAll("\\s{2}", " "); // replaces exactly two consecutive spaces
sampleString.replaceAll("\\s{2,}", " "); // replaces two or more consecutive white spaces
String txt = "whatever my string is";
txt.replaceAll("\\p{Zs}+", " ")