#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 )