Удалите пробелы в скобках, кроме текста в кавычках

Aug 19 2020

Я ищу регулярное выражение, которое может удалять пробелы, когда они находятся между соответствующими скобками, то есть (и ), за исключением случаев , когда внутри скобок есть пробелы внутри кавычек ( 'или ") .

В настоящее время у меня есть регулярное выражение \s+(?=[^(]*\)), которое удаляет все пробелы, найденные между скобками. Так же и при наличии пробелов в кавычках.

// 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")

Более того:

  • Кавычки можно найти только внутри скобок
  • "В ' 'тексте может быть : text='text with " inside', без \escape-символа.
  • 'В " "тексте может быть : text="text with ' inside", без \escape-символа.
  • Перед кавычками в строке нет escape-символа:text='This is \" not there'

Я знаю, что есть довольно много вопросов о шаблонах регулярных выражений, но я не смог найти ни одного, который помог бы. Среди многих вещей, которые я пробовал, были поиски только промежуточных значений (до 'или "с \s+(?=[^("]*[\)"]), но это все еще находит пробелы между "и ".

Может ли кто-нибудь указать мне в правильном направлении?

Ответы

1 AbdessabourMtk Aug 19 2020 at 19:06

Я внес некоторые изменения в регулярное выражение, которое вы использовали:

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

регулярное выражение разделено на две части, регулярное выражение будет соответствовать любой из них:

  1. первая часть (?<!['"][^,]*)\s+(?=[^(]*\))соответствует как можно большему количеству пробелов, \s+которым не предшествует кавычка '"( (?<!['"][^,]*)), и если только за ней следует закрывающая скобка.(?=[^(]*\))
  2. вторая часть \s+(?![^,]*['"])(?=[^(]*\))соответствует как можно большему количеству пробелов , за \s+которыми не следует кавычка, (?![^,]*['"])и только если за ней следует закрывающая скобка (?=[^(]*\)).

вы можете протестировать это здесь

2 DmitryBychenko Aug 19 2020 at 02:27

Ну, так как у вас есть два вида цитат, "и 'вам приходится иметь дело с цитатой цитаты :

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

Обратите внимание, что оба апострофа заключены в кавычки и поэтому не работают. То же самое со скобками . Я сомневаюсь, что здесь поможет простое регулярное выражение, но конечный автомат может:

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

Демо:

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

Console.WriteLine(RemoveSpaces(test));

Исход:

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