WhiteSpace Matching Regex – Java

de Java API voor reguliere uitdrukkingen stelt dat \skomt overeen met WhiteSpace. Dus de regex \\s\\smoet overeenkomen met twee ruimtes.

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

Het doel hiervan is om alle gevallen van twee opeenvolgende witruimte te vervangen door een enkele ruimte. Dit werkt echter niet.

Heb ik een ernstig misverstand van regexes of de term “witruimte”?


Antwoord 1, Autoriteit 100%

Ja, u moet het resultaat van matcher.replaceAll():

pakken

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

Antwoord 2, Autoriteit 460%

U kunt niet gebruiken \sin JAVA om te passen bij White Space op zijn eigen inheemse tekenset, omdat Java de woning Unicode White Space niet ondersteunt – ook al is het ten strengste vereist Maak kennis met uts # 18’s rl1.2! Wat het wel heeft is geen normen-conforme, helaas.

Unicode definieert 26 codepunten als \p{White_Space}: 20 van hen zijn verschillende soorten \pZalgemene opdracht = separator , en De resterende 6 zijn \p{Cc}algemene opdracht = controle .

White Space is een vrij stabiel eigendom, en diezelfde zijn vrijwel voor altijd rond. Toch heeft Java geen eigendom dat hiervoor voldoet aan de Unicode-standaard, zodat u in plaats daarvan code hoeft te gebruiken:

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

Nu kunt u whitespace_charclass + "+"gebruiken als het patroon in uw replaceAll.


Sorry ’bout alles. Java’s Regexes werken gewoon niet goed op zijn eigen inheemse tekenset, en dus moet je echt door exotische hoepels springen om ze te laten werken.

En als u denkt dat White Space slecht is, moet u zien wat u moet doen om \wen \bte krijgen om Eindelijk goed te gedragen!

Ja, het is mogelijk, en ja, het is een MindNumbing-puinhoop. Dat is liefdadig, zelfs. De gemakkelijkste manier om een ​​normen-complementerende Regex-bibliotheek voor Java te krijgen, is naar JNI naar ICU’s dingen. Dat is wat Google doet voor Android, omdat orasun’s niet meet.

Als u dat niet wilt doen, maar nog steeds bij Java wilt blijven, heb ik een front-end regex-herschrijfbibliotheek die ik heb geschreven dat “fixeert” Java’s patronen, tenminste om ze te halen aan de vereisten van rl1.2a in uts # 18, Unicode reguliere uitdrukkingen .


Antwoord 3, Autoriteit 36%

Voor Java (niet PHP, niet JavaScript, niet enig ander):

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

Antwoord 4, Autoriteit 11%

Toen ik een vraag heb verstuurd naar een Regexbuddy (Regex Developer Application) Forum, kreeg ik meer exacte antwoord op mijn \ s Java-vraag:

“Bericht Auteur: Jan Goyvaerts

In Java bevatten de afkortingen \s, \d en \w alleen ASCII-tekens. … Dit is geen bug in Java, maar gewoon een van de vele dingen waar je op moet letten bij het werken met reguliere expressies. Om alle Unicode-spaties en regeleinden overeen te laten komen, kunt u [\s\p{Z}] in Java gebruiken. RegexBuddy ondersteunt nog geen Java-specifieke eigenschappen zoals \p{javaSpaceChar} (die overeenkomt met exact dezelfde tekens als [\s\p{Z}]).

… \s\s komen overeen met twee spaties, als de invoer alleen ASCII is. Het echte probleem zit in de code van de OP, zoals blijkt uit het geaccepteerde antwoord op die vraag.”


Antwoord 5, autoriteit 9%

Het lijkt voor mij te werken:

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

zal afdrukken:

" a  b   c"

Ik denk dat je van plan was dit te doen in plaats van je code:

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

Antwoord 6, autoriteit 7%

Voor uw doel kunt u dit fragment gebruiken:

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

Hierdoor wordt de spatiëring genormaliseerd naar enkelvoudig en worden ook de begin- en volgende spaties verwijderd.

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

Antwoord 7, autoriteit 4%

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

Antwoord 8, autoriteit 4%

Java is geëvolueerd sinds dit probleem voor het eerst ter sprake kwam. U kunt allerlei unicode-spatietekens matchen door de groep \p{Zs}te gebruiken.

Als u dus een of meer exotische ruimten wilt vervangen door een gewone ruimte, kunt u dit doen:

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

Ook de moeite waard om te weten, als je de stringfunctie trim()hebt gebruikt, moet je eens kijken naar de (relatief nieuwe) strip(), stripLeading()en stripTrailing()functies op strings. Het kan u helpen allerlei soorten eekhoornachtige witruimtetekens af te snijden. Voor meer informatie over welke ruimte is inbegrepen, zie Java’s functie Character.isWhitespace().


Antwoord 9

Het gebruik van witruimte in RE is lastig, maar ik geloof dat ze werken. Het probleem van de OP kan ook worden opgelost met behulp van StringTokenizer of de methode split(). Als u echter RE wilt gebruiken (verwijder de opmerking bij de println() om te zien hoe de matcher de String opbreekt), volgt hier een voorbeeldcode:

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) + "\"");
}}

Het produceert het volgende (compileer met Javac en wordt uitgevoerd op de opdrachtprompt):

% java twee21WS
Eerste: “A B CDEF GH IJ KL”
Two21Ws: “A B CDEF GH IJ KL”

Other episodes