Как удалить пробелы между конкретными словами с помощью регулярного выражения?

#c# #regex

#c# #регулярное выражение

Вопрос:

Я хочу удалить пробелы из определенного слова в строке. Например, рассмотрим приведенный ниже запрос в качестве входной строки

 SELECT LTRIM ( RTRIM ( [EMPOYEE_NAME] ) ), LTRIM ( RTRIM ( [EMPOYEE_ADDR] ) ), LTRIM ( RTRIM ( [EMPOYEE_TYPE] ) ) FROM EMPLOYEE WHERE ( EMPLOYEE_ID = @EMPLOYEE_ID )
  

Теперь я хочу удалить пробелы между фигурными скобками LTRIM, RTRIM и содержимым внутри него, а не из всей строки.

Таким образом, конечный результат должен быть

 SELECT LTRIM(RTRIM([EMPOYEE_NAME])), LTRIM(RTRIM([EMPOYEE_ADDR])), LTRIM(RTRIM([EMPOYEE_TYPE])) FROM EMPLOYEE WHERE ( EMPLOYEE_ID = @EMPLOYEE_ID )
  

Я пробовал следующее решение, но оно заменяет все пробелы —

 var source = "SELECT LTRIM ( RTRIM ( [EMPOYEE_NAME] ) ), LTRIM ( RTRIM
( [EMPOYEE_ADDR] ) ), LTRIM ( RTRIM ( [EMPOYEE_TYPE] ) ) FROM EMPLOYEE
WHERE ( EMPLOYEE_ID = @EMPLOYEE_ID )";

source = Regex.Replace(source, "\s(\s?)\s*", "$1");
  

Итак, возможно ли создать регулярное выражение для удаления пробелов только из определенных слов в строке?

Приветствуются любые предложения.

Комментарии:

1. В общем случае вам нужен анализатор , поскольку LTRIM он может отображаться как часть строки, комментария и т.д. select 'my LTRIM ((' as "LTRIM (())" from dual -- LTRIM ( — здесь у нас есть строка , цитата и комментарий , которые должны быть сохранены в целости

2. В дополнение к вышесказанному, честно говоря, это то, что должно обрабатываться вашей IDE, в которой, вероятно, есть функция очистки кода. Я уверен, что это существует для IntelliJ и Eclipse, не уверен насчет Visual Studio.

3. Если ваши подстроки, где пробелы должны быть удалены, могут быть сопоставлены с @"bLTRIMs*(s*RTRIMs*([^()]*)s*)" , проблема может быть решена с помощью одного регулярного выражения.

Ответ №1:

Я бы использовал lookbehind и lookahead:

 var source = "SELECT LTRIM ( RTRIM ( [EMPOYEE_NAME] ) ), LTRIM ( RTRIM ( [EMPOYEE_ADDR] ) ), LTRIM ( RTRIM ( [EMPOYEE_TYPE] ) ) FROM EMPLOYEE WHERE ( EMPLOYEE_ID = @EMPLOYEE_ID )";
source = Regex.Replace(source, @"((?<=LTRIM)(s)|(?<=RTRIM)s (?=()|(?<=()s |s (?=)))", "");
Console.WriteLine(source);
  

Вывод:

 SELECT LTRIM(RTRIM([EMPOYEE_NAME])), LTRIM(RTRIM([EMPOYEE_ADDR])), LTRIM(RTRIM([EMPOYEE_TYPE])) FROM EMPLOYEE WHERE (EMPLOYEE_ID = @EMPLOYEE_ID)
  

Тест и объяснение: https://regex101.com/r/agq0V5/1

Примечание: для упрощения также будут удалены пробелы внутри WHERE фигурных скобок, это так плохо?

Редактировать

Здесь решение связывает группы без совпадающих пробелов внутри WHERE фигурных скобок.

 var source = "SELECT LTRIM ( RTRIM ( [EMPOYEE_NAME] ) ), LTRIM ( RTRIM ( [EMPOYEE_ADDR] ) ), LTRIM ( RTRIM ( [EMPOYEE_TYPE] ) ) FROM EMPLOYEE WHERE ( EMPLOYEE_ID = @EMPLOYEE_ID )";
source = Regex.Replace(source, @"(LTRIM)(s*)(()(s*)(RTRIM)(s*)(()(s*)([^ ]*)(s*)())(s*)())", "$1$3$5$7$9$11$13");
Console.WriteLine(source);
  

Вывод:

 SELECT LTRIM(RTRIM([EMPOYEE_NAME])), LTRIM(RTRIM([EMPOYEE_ADDR])), LTRIM(RTRIM([EMPOYEE_TYPE])) FROM EMPLOYEE WHERE ( EMPLOYEE_ID = @EMPLOYEE_ID )
  

ПРАВКА 2

Другим решением было бы удалить FROM часть, затем заменить пробелы возле фигурных скобок, затем добавить недостающую часть.

 var source = "SELECT LTRIM ( RTRIM ( [EMPOYEE_NAME] ) ), LTRIM ( RTRIM ( [EMPOYEE_ADDR] ) ), LTRIM ( RTRIM ( [EMPOYEE_TYPE] ) ) FROM EMPLOYEE WHERE ( EMPLOYEE_ID = @EMPLOYEE_ID )";
var from_part = Regex.Match(source,  @"FROM.*");
var partial_source = Regex.Replace(source, @"FROM.*", "");

source = Regex.Replace(partial_source, @"(s (?=))|(s (?=())|(?<=()(s ))", "");

var final_string = source   from_part.Value;
Console.WriteLine(final_string);
  

Вывод:

 SELECT LTRIM(RTRIM([EMPOYEE_NAME])), LTRIM(RTRIM([EMPOYEE_ADDR])), LTRIM(RTRIM([EMPOYEE_TYPE])) FROM EMPLOYEE WHERE ( EMPLOYEE_ID = @EMPLOYEE_ID )
  

Это также будет соответствовать LTRIM() RTRIM() LTRIM(RTRIM()) RTRIM(LTRIM()) и любым другим комбинациям.

Тест и объяснение: https://regex101.com/r/28nfTE/1

Комментарии:

1. Спасибо, @ALFA — Но не ожидается удаления пробелов из любой другой строки, кроме LTRIM RTRIM. Будет ли это возможно, если порядок LTRIM и RTRIM изменится? Поскольку его динамическая строка и строка ввода могут иметь любую комбинацию, такую как LTRIM(RTRIM (имя столбца)) Или LTRIM() Или RTRIM() или RTRIM(LTRIM(имя столбца))

2. Проверьте мой ответ сейчас, я добавил альтернативное решение по вашему запросу. Вам следует добавить к нему альтернативы, сейчас слишком сложно также сопоставлять пустые фигурные скобки и RTRIM(LTRIM()). Тем временем я попытаюсь придумать способ получше.

3. Проверьте мою правку 2, посмотрите, соответствует ли она вашим потребностям.

Ответ №2:

Используйте возможности MatchEvaluator замены для выполнения фактической грязной работы.

Используя базовый шаблон s([LR])TRIMs , мы определим наши целевые слова TRIM с пробелами. В рамках этого шаблона мы создадим подгруппу, которая будет определять с помощью L или R того, что необходимо предоставить, и что находится в .group[1].value . Следовательно, эта группа подскажет нам, вставлять ли пробел {SP}LTRIM или нет RTRIM .

 string txt = "SELECT LTRIM ( RTRIM ( [EMPOYEE_NAME] ) ), LTRIM ( RTRIM ( [EMPOYEE_ADDR] ) ), LTRIM ( RTRIM ( [EMPOYEE_TYPE] ) ) FROM EMPLOYEE WHERE ( EMPLOYEE_ID = @EMPLOYEE_ID  )";

Regex.Replace(txt, @"s([LR])TRIMs", new MatchEvaluator( mtch => {

return (mtch.Groups[1].Value == "L") ? $" LTRIM" : "RTRIM";

} ));
  

ВОЗВРАТ

  SELECT LTRIM(RTRIM( [EMPOYEE_NAME] ) ), LTRIM(RTRIM( [EMPOYEE_ADDR] ) ), LTRIM(RTRIM( [EMPOYEE_TYPE] ) ) FROM EMPLOYEE WHERE ( EMPLOYEE_ID = @EMPLOYEE_ID  )