Regex Frage - Ein oder mehrere Räume außerhalb eines Zitats geschlossenen Textblock

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

  •  06-07-2019
  •  | 
  •  

Frage

Ich mag jedes Auftreten mit einem einzigen Raum von mehr als einen Raum ersetzen sein, aber keine Aktion in Text in Anführungszeichen nehmen.

Gibt es eine Möglichkeit, dies mit einem Java-Regex zu tun? Wenn ja, können Sie es bitte versuchen oder einen Tipp geben mir?

War es hilfreich?

Lösung

Hier ist ein weiterer Ansatz verwendet, dass ein Look-Ahead, um festzustellen, dass alle Anführungszeichen nach der aktuellen Position kam in matched pairs.

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

Bei Bedarf kann der Look-Ahead angepasst werden zu handhaben entkam Anführungszeichen in den genannten Abschnitten.

Andere Tipps

Beim Versuch, etwas zu entsprechen, die sonst in etwas enthalten sein kann, kann es hilfreich sein, einen regulären Ausdruck zu konstruieren, die beide übereinstimmt, wie folgt aus:

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

Dies wird eine Zeichenfolge in Anführungszeichen oder zwei oder mehr Räume entsprechen. Da die beiden Ausdrücke kombiniert werden, wird es eine Zeichenfolge in Anführungszeichen oder zwei oder mehr Räume passen, aber keine Leerzeichen in Anführungszeichen. Mit diesem Ausdruck, müssen Sie jedes Spiel zu untersuchen, um festzustellen, ob es sich um eine Zeichenfolge in Anführungszeichen oder zwei oder mehr Räume und entsprechend handeln:

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

Text in Anführungszeichen: Sind die Anführungszeichen innerhalb der gleichen Zeile oder mehrere Zeilen

?

tokenize es und einen einzigen Raum zwischen Token emittieren. Eine schnelle Google für „Java tokenizer, die Anführungszeichen behandelt“ aufgedreht: diesen Link

YMMV

edit: SO nicht auf diesen Link gefallen hat. Hier ist die Google-Suche Link: google . Es war das erste Ergebnis.

Ich persönlich nicht verwenden Java, aber das RegExp könnte den Trick tun:

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

Der Versuch, den Ausdruck mit RegexBuddy, erzeugt es diesen Code, sieht gut zu mir:

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
}

Zumindest scheint es in Python zu funktionieren:

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

Nachdem Sie den angegebenen Inhalt analysieren, führen Sie dies auf dem Rest, in loser Schüttung oder Stück für Stück nach Bedarf an:

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

Jeff, Sie auf dem richtigen Weg sind, aber es gibt ein paar Fehler im Code, nämlich: (1) Sie haben vergessen, die Anführungszeichen in den negierten Zeichenklassen zu entkommen; (2) Die Pars innerhalb der ersten Erfassungsgruppe sollten die Nicht-Erfassung Vielzahl haben; (3) Wenn der zweite Satz für den Fang von Pars nicht in einem Spiel teilnehmen, gibt group(2) null, und Sie testen nicht dafür; und (4) Wenn Sie testen für zwei oder mehr Räume in dem regex anstelle von einem oder mehr , Sie brauchen nicht auf die Länge des Spiels später zu überprüfen. Hier ist der überarbeitete Code:

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() );
  }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top