Question Regex - Un ou plusieurs espaces en dehors d'une citation, bloc de texte fermé

StackOverflow https://stackoverflow.com/questions/263985

  •  06-07-2019
  •  | 
  •  

Question

Je souhaite remplacer toute occurrence de plusieurs espaces par un seul, mais aucune action en texte entre guillemets.

Existe-t-il un moyen de faire cela avec une expression rationnelle Java? Si oui, pouvez-vous essayer ou me donner un indice?

Était-ce utile?

La solution

Voici une autre approche, qui consiste à regarder avant pour déterminer que tous les guillemets après la position actuelle sont placés par paires.

text = text.replaceAll("  ++(?=(?:[^\"]*+\"[^\"]*+\")*+[^\"]*+$)", " ");

Si nécessaire, le lookahead peut être adapté pour gérer les guillemets échappés à l'intérieur des sections citées.

Autres conseils

Lorsque vous essayez de faire correspondre quelque chose qui peut être contenu dans quelque chose d'autre, il peut être utile de construire une expression régulière qui correspond aux deux, comme ceci:

("[^"\\]*(?:\\.[^"\\]*)*")|(  +)

Ceci correspondra à une chaîne entre guillemets ou à deux espaces ou plus. Comme les deux expressions sont combinées, cela correspond à une chaîne entre guillemets OU à deux espaces ou plus, mais pas aux guillemets. En utilisant cette expression, vous devrez examiner chaque correspondance pour déterminer s’il s’agit d’une chaîne entre guillemets ou de deux espaces ou plus et agir en conséquence:

Pattern spaceOrStringRegex = Pattern.compile( "(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\")|(  +)" );

StringBuffer replacementBuffer = new StringBuffer();

Matcher spaceOrStringMatcher = spaceOrStringRegex.matcher( text );

while ( spaceOrStringMatcher.find() ) 
{
    // if the space group is the match
    if ( spaceOrStringMatcher.group( 2 ) != null ) 
    {
        // replace with a single space
        spaceOrStringMatcher.appendReplacement( replacementBuffer, " " );
    }
}

spaceOrStringMatcher.appendTail( replacementBuffer );

texte entre guillemets: les guillemets sont-ils sur la même ligne ou sur plusieurs lignes?

Tokenisez-le et émettez un seul espace entre les jetons. Un google rapide pour "Jetonizer Java qui gère les guillemets". tourné: ce lien

YMMV

edit: SO n'a pas aimé ce lien. Voici le lien de recherche Google: google . C'était le premier résultat.

Personnellement, je n'utilise pas Java, mais cette RegExp pourrait faire l'affaire:

([^\" ])*(\\\".*?\\\")*

Essayer l'expression avec RegExBuddy, il génère ce code, il me semble bien:

try {
    Pattern regex = Pattern.compile("([^\" ])*(\\\".*?\\\")*", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
    Matcher regexMatcher = regex.matcher(subjectString);
    while (regexMatcher.find()) {
        for (int i = 1; i <= regexMatcher.groupCount(); i++) {
            // matched text: regexMatcher.group(i)
            // match start: regexMatcher.start(i)
            // match end: regexMatcher.end(i)

            // I suppose here you must use something like
            // sstr += regexMatcher.group(i) + " "
        }
    }
} catch (PatternSyntaxException ex) {
    // Syntax error in the regular expression
}

Au moins, cela semble fonctionner correctement en Python:

import re

text = """
este  es   un texto de   prueba "para ver  como se comporta  " la funcion   sobre esto
"para ver  como se comporta  " la funcion   sobre esto  "o sobre otro" lo q sea
"""

ret = ""
print text  

reobj = re.compile(r'([^\" ])*(\".*?\")*', re.IGNORECASE)

for match in reobj.finditer(text):
    if match.group() <> "":
        ret = ret + match.group() + "|"

print ret

Après avoir analysé le contenu cité, exécutez ce travail sur le reste, en bloc ou pièce par pièce, si nécessaire:

String text = "ABC   DEF GHI   JKL";
text = text.replaceAll("( )+", " ");
// text: "ABC DEF GHI JKL"

Jeff, vous êtes sur la bonne voie, mais votre code contient quelques erreurs, à savoir: (1) vous avez oublié d'échapper aux guillemets dans les classes de caractères annulées; (2) Les parenthèses du premier groupe de capture auraient dû appartenir à la variété sans capture; (3) Si le deuxième ensemble d'entités capturantes ne participe pas à une correspondance, group (2) renvoie la valeur null et vous ne testez pas pour cela; et (4) Si vous testez deux ou plus espaces dans la regex au lieu de un ou plusieurs , vous n'avez pas besoin de vérifier la longueur de la correspondance ultérieurement. Voici le code révisé:

import java.util.regex.*;

public class Test
{
  public static void main(String[] args) throws Exception
  {
    String text = "blah    blah  \"boo   boo boo\"  blah  blah";
    Pattern p = Pattern.compile( "(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\")|(  +)" );
    StringBuffer sb = new StringBuffer();
    Matcher m = p.matcher( text );
    while ( m.find() ) 
    {
      if ( m.group( 2 ) != null ) 
      {
        m.appendReplacement( sb, " " );
      }
    }
    m.appendTail( sb );
    System.out.println( sb.toString() );
  }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top