web-dev-qa-db-ja.com

空白一致正規表現-Java

正規表現 のJava AP​​Iは、\sが空白に一致することを示しています。したがって、正規表現\\s\\sは2つのスペースに一致する必要があります。

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

これの目的は、2つの連続した空白のすべてのインスタンスを単一のスペースに置き換えることです。ただし、これは実際には機能しません。

正規表現または「ホワイトスペース」という用語の重大な誤解がありますか?

93
Glenn Nelson

ええ、matcher.replaceAll()の結果を取得する必要があります。

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

JavaはUnicodeの空白プロパティをサポートしていないため、Javaで\sを使用して独自のネイティブ文字セットの空白を一致させることはできません。満たすために TS#18のRL1.2! それが持っているのは、標準に準拠していないことです。

Unicodeでは、26個のコードポイントを\p{White_Space}として定義しています。そのうち20個はさまざまな種類の\pZGeneralCategory = 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の正規表現は、独自のネイティブ文字セットではうまく機能しません。したがって、エキゾチックな輪を飛び越えて機能させる必要があります。

また、空白が悪いと思う場合は、\w\bを最終的に適切に動作させるために何をする必要があるかを確認する必要があります。

はい、それは可能です、そして、はい、それは気が散る混乱です。それは慈善でもありますJavaの標準準拠の正規表現ライブラリを取得する最も簡単な方法は、JNIからICUのものに移動することです。 OraSunはAndroidに対応していないため、これはGoogleがAndroidで行っていることです。

それをしたくないがJavaに固執したい場合は、少なくとも RL1の要件に準拠させるために、Javaのパターンを「修正」するように記述したフロントエンドの正規表現書き換えライブラリがあります.2a UTS#18、Unicode Regular Expressions

=end soapbox

173
tchrist

Javaの場合(phpでも、javascriptでも、他でもない):

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

regexbuddy(regex開発者アプリケーション)フォーラムに質問を送信すると、\ s Java質問に対してより正確な回答が得られました。

「メッセージ作成者:Jan Goyvaerts

Javaでは、略記\ s、\ d、および\ wにはASCII文字のみが含まれます。 ...これはJavaのバグではありませんが、正規表現を使用する際に注意する必要がある多くのことの1つにすぎません。すべてのUnicode空白と改行を一致させるには、Javaで[\ s\p {Z}]を使用できます。 RegexBuddyは、\ p {javaSpaceChar}([\ s\p {Z}]とまったく同じ文字に一致)などのJava固有のプロパティをまだサポートしていません。

...入力がASCIIのみの場合、\ s\sは2つのスペースに一致します。本当の問題はOPのコードにあり、その質問で受け入れられた答えによって指摘されています。」

5
Tuomas

私のために働くようです:

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);
4
Mihai Toader

あなたの目的のために、このスニペットを使用できます:

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

これにより、間隔が単一に正規化され、開始および末尾の空白も削除されます。

あなたの目的のために、このスニペットを使用できます:

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

これにより、間隔が単一に正規化され、開始および末尾の空白も削除されます。

String sampleString = "Hello world!"; sampleString.replaceAll( "\ s {2}"、 ""); //ちょうど2つの連続したスペースを置き換えます

sampleString.replaceAll( "\ s {2、}"、 ""); // 2つ以上の連続する空白を置き換えます

1
Rashid Mv
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;
 }
}
1
Mike