Remova os espaços entre colchetes, exceto para o texto entre aspas
Estou procurando um regex que pode remover espaços quando eles estão entre colchetes correspondentes, ou seja , (
e )
, exceto quando há espaços entre aspas ( '
ou "
) dentro dos colchetes.
Atualmente tenho o regex \s+(?=[^(]*\))
, que remove todos os espaços encontrados entre colchetes. O mesmo ocorre quando há espaços entre aspas.
// 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")
Além disso:
- As aspas só podem ser encontradas dentro dos colchetes
- Pode haver
"
em'
'
texto:,text='text with " inside'
sem o\
caractere de escape. - Pode haver
'
em"
"
texto:,text="text with ' inside"
sem o\
caractere de escape. - Não há caractere de escape antes das aspas na string:
text='This is \" not there'
Eu sei que existem algumas perguntas sobre os padrões de regex, mas não consegui encontrar uma que resolvesse o problema. Entre as muitas coisas que tentei foi olhar para a frente para encontrar apenas coisas entre (
até '
ou "
com \s+(?=[^("]*[\)"])
, mas que ainda encontra os espaços entre "
e "
.
Alguém pode me apontar na direção certa?
Respostas
Fiz algumas modificações na expressão regular que você usou:
# match a space or more
# if the fol
(?<!['"][^,]*)\s+(?=[^(]*\))|\s+(?![^,]*['"])(?=[^(]*\))
a expressão regular é dividida em duas partes, a expressão regular corresponderá a uma delas:
- a primeira parte
(?<!['"][^,]*)\s+(?=[^(]*\))
corresponde ao máximo de espaço em branco possível\s+
que não seja precedido por aspas'"
((?<!['"][^,]*)
) e se apenas for seguido por um parêntese de fechamento.(?=[^(]*\))
- a segunda parte
\s+(?![^,]*['"])(?=[^(]*\))
corresponde ao máximo de espaço em branco possível\s+
que não(?![^,]*['"])
seja seguido por uma aspa e somente se for seguido por um parêntese de fechamento(?=[^(]*\))
.
você pode testar aqui
Bem, já que você tem dois tipos de citações, "
e '
você tem que lidar com a citação de citação :
abc"def pqr' ijk" "klm ' xyz"
Observe que ambos os apóstrofos são enquotados e é por isso que não funcionam. Mesmo com colchetes . Duvido que uma simples expressão regular possa ajudar aqui, mas Finite State Machine pode:
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));
Resultado:
do something with(in=1,text='some text with spaces',text2="also has spaces")