Rimuovi gli spazi tra parentesi ad eccezione del testo tra virgolette
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
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:
- 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.(?=[^(]*\))
- 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
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")