Rimuovi gli spazi tra parentesi ad eccezione del testo tra virgolette

Aug 19 2020

Sto cercando una regex che possa rimuovere gli spazi quando sono tra parentesi graffe corrispondenti, cioè (e ), tranne quando ci sono spazi tra virgolette ( 'o ") all'interno delle parentesi.

Al momento ho la regex \s+(?=[^(]*\)), che rimuove tutti gli spazi trovati tra parentesi. Quindi anche quando ci sono spazi tra virgolette.

// My input
do something with(in = 1, text='some text with spaces' , text2="also has spaces")

// My current output
do something with(in=1,text='sometextwithspaces',text2="alsohasspaces")

// My desired output
do something with(in=1,text='some text with spaces',text2="also has spaces")

Inoltre:

  • Le virgolette possono essere trovate solo all'interno delle parentesi
  • Ci può essere "nel ' 'testo:, text='text with " inside'senza il \carattere di escape.
  • Ci può essere 'nel " "testo:, text="text with ' inside"senza il \carattere di escape.
  • Non è presente alcun carattere di escape prima delle virgolette nella stringa:text='This is \" not there'

So che ci sono alcune domande sui pattern regex, ma non sono riuscito a trovarne uno che abbia funzionato. Tra le tante cose che ho provato c'era guardare avanti per trovare solo cose tra (fino a 'o "con \s+(?=[^("]*[\)"]), ma che trova ancora gli spazi tra "e ".

Qualcuno può indicarmi la giusta direzione?

Risposte

1 AbdessabourMtk Aug 19 2020 at 19:06

Ho apportato alcune modifiche all'espressione regolare che hai usato:

# match a space or more 
# if the fol
(?<!['"][^,]*)\s+(?=[^(]*\))|\s+(?![^,]*['"])(?=[^(]*\))

l'espressione regolare è divisa in due parti, l'espressione regolare corrisponderà a una di esse:

  1. la prima parte (?<!['"][^,]*)\s+(?=[^(]*\))corrisponde a quanto più spazio bianco possibile \s+che non è preceduto da virgolette '"( (?<!['"][^,]*)) e se solo è seguito da una parentesi di chiusura.(?=[^(]*\))
  2. la seconda parte \s+(?![^,]*['"])(?=[^(]*\))corrisponde a quanto più spazio bianco possibile \s+che non è seguito da una citazione (?![^,]*['"])e solo se è seguita da una parentesi di chiusura (?=[^(]*\)).

puoi provarlo qui

2 DmitryBychenko Aug 19 2020 at 02:27

Bene, dal momento che hai due tipi di citazioni "e 'devi occuparti della citazione della citazione :

  abc"def pqr' ijk" "klm ' xyz"

Nota che entrambi gli apostrofi sono enquisiti ed è per questo che non funzionano. Lo stesso con le parentesi . Dubito che una semplice espressione regolare possa aiutare qui, ma Finite State Machine può:

private static string RemoveSpaces(string value) {
  if (string.IsNullOrEmpty(value))
    return value;

  bool inQuotation = false;
  bool inApostroph = false;
  int bracketCount = 0;
  int escapeCount = 0;
  StringBuilder result = new StringBuilder(value.Length);

  foreach (char c in value) {
    if (inQuotation) {
      result.Append(c);
      inQuotation = c != '"' || (escapeCount % 2 != 0);
    }
    else if (inApostroph) {
      result.Append(c);
      inApostroph = c != '\'' || (escapeCount % 2 != 0);
    }
    else {
      if (c != ' ' || bracketCount <= 0)
        result.Append(c);

      if (c == '(')
        bracketCount += 1;
      else if (bracketCount == ')')
        bracketCount -= 1;

      inQuotation = c == '"' && (escapeCount % 2 == 0);
      inApostroph = c == '\'' && (escapeCount % 2 == 0);
    }

    escapeCount = c == '\\' ? escapeCount + 1 : 0;
  }
  return result.ToString();
}

Demo:

string test =
  @"do something with(in = 1, text='some text with spaces' , text2=""also has spaces"")";

Console.WriteLine(RemoveSpaces(test));

Risultato:

do something with(in=1,text='some text with spaces',text2="also has spaces")