wake-up-neo.com

Whitespace Matching Regex - Java

Die Java API für reguläre Ausdrücke besagt, dass \s stimmt mit Leerzeichen überein. Also der Regex \\s\\s sollte mit zwei Leerzeichen übereinstimmen.

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

Ziel ist es, alle Instanzen von zwei aufeinanderfolgenden Whitespaces durch ein Leerzeichen zu ersetzen. Dies funktioniert jedoch nicht wirklich.

Habe ich ein schwerwiegendes Missverständnis von Regexen oder dem Begriff "Whitespace"?

94
user372743

Ja, Sie müssen das Ergebnis von matcher.replaceAll () abrufen:

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

Sie können \s In Java) nicht verwenden, um Leerzeichen in einem eigenen nativen Zeichensatz abzugleichen, da Java den Unicode nicht unterstützt Leerraumeigenschaft - obwohl dies unbedingt erforderlich ist, um TS # 18's RL1.2! zu erfüllen. Was es hat, ist leider nicht normkonform.

Unicode definiert 26 Codepunkte als \p{White_Space}: 20 davon sind verschiedene Arten von \pZ GeneralCategory = Separator und die restlichen 6 sind \p{Cc} GeneralCategory = Control.

Leerraum ist eine ziemlich stabile Eigenschaft, und die gleichen gibt es praktisch schon seit Ewigkeiten. Trotzdem hat Java keine dem Unicode-Standard entsprechende Eigenschaft, sodass Sie stattdessen Code wie diesen verwenden müssen:

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 + "]";

Jetzt können Sie whitespace_charclass + "+" Als Muster in Ihrem replaceAll verwenden.


Entschuldigung. Die regulären Ausdrücke von Java funktionieren mit dem eigenen nativen Zeichensatz nicht besonders gut . Sie müssen also wirklich durch exotische Rahmen springen, damit sie funktionieren.

Und wenn Sie der Meinung sind, dass Leerzeichen schlecht sind, sollten Sie sehen, was Sie tun müssen, um \w Und \b Zu erhalten, um sich endlich richtig zu verhalten!

Ja, das ist möglich, und ja, es ist ein verdammtes Durcheinander. Das ist sogar gemeinnützig. Der einfachste Weg, eine standardkonforme Regex-Bibliothek für Java zu erhalten, besteht darin, JNI auf die ICU-Inhalte zu übertragen. Genau das macht Google für Android, da OraSun nicht mithalten kann.

Wenn Sie das nicht tun möchten, aber trotzdem bei Java bleiben möchten, habe ich eine Front-End-Bibliothek zum Umschreiben von Regex, die Java-Muster „repariert“, um sie zumindest an die Anforderungen von RL1 anzupassen .2a in UTS # 18, Unicode Regular Expressions .

174
tchrist

Für Java (kein PHP, kein Javascript, kein anderes):

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

als ich eine Frage an ein Regexbuddy-Forum (Regex-Entwickleranwendung) sendete, erhielt ich eine genauere Antwort auf meine Frage Java:

"Verfasser der Nachricht: Jan Goyvaerts

In Java enthalten die Abkürzungen\s,\d und\w nur ASCII Zeichen. ... Dies ist kein Fehler in Java, sondern nur eines der vielen Dinge, die Sie beim Arbeiten mit regulären Ausdrücken beachten müssen. Um alle Unicode-Leerzeichen sowie Zeilenumbrüche abzugleichen, können Sie in Java [\ s\p {Z}] verwenden. RegexBuddy unterstützt noch keine Java-spezifischen Eigenschaften wie\p {javaSpaceChar} (die genau den gleichen Zeichen entsprechen wie [\ s\p {Z}]).

...\s\s stimmt mit zwei Leerzeichen überein, wenn die Eingabe nur ASCII ist. Das eigentliche Problem ist der OP-Code, wie die akzeptierte Antwort in dieser Frage zeigt. "

5
Tuomas

Scheint für mich zu arbeiten:

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

wird drucken:

" a  b   c"

Ich denke, Sie wollten dies anstelle Ihres Codes tun:

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

System.out.println(result);
3
Mihai Toader

Für Ihren Zweck können Sie dieses Snnippet verwenden:

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

dadurch wird der Abstand auf "single" normalisiert und die anfänglichen und nachfolgenden Leerzeichen werden ebenfalls entfernt.

Für Ihren Zweck können Sie dieses Snnippet verwenden:

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

dadurch wird der Abstand auf "single" normalisiert und die anfänglichen und nachfolgenden Leerzeichen werden ebenfalls entfernt.

String sampleString = "Hallo Welt!"; sampleString.replaceAll ("\ s {2}", ""); // ersetzt genau zwei aufeinanderfolgende Leerzeichen

sampleString.replaceAll ("\ s {2,}", ""); // ersetzt zwei oder mehr aufeinanderfolgende Leerzeichen

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