web-dev-qa-db-fra.com

Regex correspondant à des espaces blancs - Java

L'API Java pour expressions régulières indique que \s correspondra à un espace. Ainsi, l'expression régulière \\s\\s devrait correspondre à deux espaces.

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

L'objectif est de remplacer toutes les occurrences de deux espaces consécutifs par un seul espace. Cependant, cela ne fonctionne pas réellement.

Est-ce que j'ai un malentendu grave avec les expressions rationnelles ou le terme "espace"?

94
user372743

Oui, vous devez récupérer le résultat de matcher.replaceAll ():

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

Vous ne pouvez pas utiliser \s dans Java pour faire correspondre un espace blanc sur son propre jeu de caractères natif, car Java ne prend pas en charge la propriété Unicode, même si cela est le cas. donc est strictement nécessaire pour répondre RL1.2 de UTS # 18! Ce qu'il a n'est pas conforme aux normes, hélas.

Unicode définit 26 points de code comme \p{White_Space}: 20 d'entre eux sont de différentes sortes de \pZ GeneralCategory = Separator , et les 6 autres sont \p{Cc} GeneralCategory = Control .

L'espace blanc est une propriété assez stable, et ces mêmes-là existent depuis presque toujours. Même dans ce cas, Java ne possède aucune propriété conforme à la norme Unicode, vous devez donc utiliser un code comme celui-ci:

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

Vous pouvez maintenant utiliser whitespace_charclass + "+" comme motif dans votre replaceAll.


Désolé pour tout ça. Les expressions rationnelles de Java ne fonctionnent pas très bien avec son propre jeu de caractères natif, et vous devez donc vraiment sauter à travers des cerceaux exotiques pour les faire fonctionner.

Et si vous pensez que les espaces sont mauvais, vous devriez voir ce que vous devez faire pour que \w et \b se comporte enfin correctement!

Oui, c’est possible, et oui, c’est un gâchis mental. C’est même charitable. Le moyen le plus simple d’obtenir une bibliothèque regex conforme aux normes pour Java consiste à utiliser JNI pour le matériel d’ICU. C’est ce que Google fait pour Android, car OraSun n’est pas à la hauteur.

Si vous ne voulez pas faire cela mais que vous voulez rester avec Java, j'ai une bibliothèque de réécriture de regex front-end que j'ai écrite qui "corrige" les patterns Java, au moins pour les rendre conformes aux exigences de RL1 .2a dans UTS # 18, expressions régulières Unicode .

174
tchrist

Pour Java (ni php, ni javascript, ni aucun autre):

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

quand j’envoyais une question à un forum Regexbuddy (application pour développeurs regex), je recevais une réponse plus exacte à ma\s Java question:

"Auteur du message: Jan Goyvaerts

En Java, les raccourcis\s,\d et\w incluent uniquement les caractères ASCII. ... Il ne s'agit pas d'un bogue dans Java, mais simplement d'une des nombreuses choses à prendre en compte lors de l'utilisation d'expressions régulières. Pour faire correspondre tous les espaces Unicode ainsi que les sauts de ligne, vous pouvez utiliser [\ s\p {Z}] en Java. RegexBuddy ne supporte pas encore les propriétés spécifiques à Java telles que\p {javaSpaceChar} (qui correspond exactement aux mêmes caractères que [\ s\p {Z}]).

...\s\s correspondra à deux espaces, si l'entrée est ASCII uniquement. Le véritable problème réside dans le code du PO, comme le souligne la réponse acceptée dans cette question. "

5
Tuomas

Semble travailler pour moi:

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

imprimera:

" a  b   c"

Je pense que vous aviez l'intention de faire cela à la place de votre code:

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

Pour votre but, vous pouvez utiliser cet snnippet:

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

cela normalisera l'espacement simple et supprimera également les espaces blancs de début et de fin.

Pour votre but, vous pouvez utiliser cet snnippet:

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

cela normalisera l'espacement simple et supprimera également les espaces blancs de début et de fin.

String sampleString = "Bonjour tout le monde!"; sampleString.replaceAll ("\ s {2}", ""); // remplace exactement deux espaces consécutifs

sampleString.replaceAll ("\ s {2,}", ""); // remplace deux ou plusieurs espaces blancs consécutifs

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