Замена по регулярке

296
09 декабря 2016, 08:52

Допустим, имеется текст text1(text2)text2 нужно получить text1 (text2) text2

Пробовал сделать через замену по регулярке: ([^\s])([\(])|([\)])([^\s])

$1 $2$3 $4

, но получаю text1 ( text2 ) text3

Answer 1

Объясню, откуда взялись лишние пробелы в результате.

Регулярка срабатывает два раза, так как наличествует |.

В первый раз в параметры $1 и $2 попадут текст до открывающей скобки и сама скобка, соответственно. А параметры $3 и $4 останутся пустыми. Следовательно, выведется:

текст до скобки, пробел, открывающая скобка, пусто, пробел (лишний!), пусто.

Во второй раз, наоборот, первые два параметра останутся пустыми, а последние два захватят закрывающую скобку и текст после неё. Аналогично, выведется:

пусто, пробел (лишний!), пусто, закрывающая скобка, текст после скобки.

Предлагаю использовать перегрузку метода Replace с использованием MatchEvaluator. В таком случае регулярка получается простейшая. Но пришлось задействовать словарь с парами замен.

var dict = new Dictionary<string, string> { ["("] = " (", [")"] = ") " };
string input = "text1(text2)text3";
string pattern = @"\( | \)";
var options = RegexOptions.IgnorePatternWhitespace;
string output = Regex.Replace(input, pattern, m => dict[m.Value], options);
Console.WriteLine(output);

В комментариях к другим ответам были высказаны предположения, что пробелы нужно добавлять только в том случае, если их нет. Вероятно для этого автор использовал ([^\s]). В таком случае, для моего варианта регулярка станет следующей:

@"(?<!\s) \( | \) (?!\s)"
Answer 2

Попробуйте отлавливать не текст до скобок | после, а саму центральную часть:

Паттерн: \s?\((.*)\)\s?

Замена: " ($1) " //обратите внимание на пробелы

Пример

Answer 3

Можно заменить (?=\()|(\)) на $1 .

Если нужно сделать по одному пробелу, независимо от того, были пробелы, или нет, то заменить \s*(?:(\()|(\)))\s* на $2 $1.

Если не надо оставлять пробелов между одинаковыми скобками, то \s*(?:(\(+)|(\)+))\s* на $2 $1.

Answer 4

Не знаю сработает ли такая замена в C#.

Регулярное выражение для поиска

(?<=[^\(\s])(?=\()|(?<=\))(?=[^\)\s])

Замена: символ пробела(!!!)

Тест тут https://regex101.com/r/cV6oQ7/1

P.S. Регулярка сама ни чего не выделяет, а только находит позиции между открывающейся скобкой и символом перед ней не равным пробельному символу или открывающейся скобке ИЛИ позицию между закрывающейся скобкой и символом за ней не равным закрывающейся скобке или пробельному символу.

READ ALSO
Как определить текущий DispatcherPriority из метода который выполняет Dispatcher?

Как определить текущий DispatcherPriority из метода который выполняет Dispatcher?

Как определить текущий DispatcherPriority из метода который выполняет Dispatcher? Если я запускаю какой–то метод через Dispatcher с приоритетом (для примера)...

320
DataTableAdapter Report Viewer C# WinForms

DataTableAdapter Report Viewer C# WinForms

После компиляции приложения, не работает отчет в reportViewer если рядом с файломexe не лежит XML файл, в котором при компиляции прописывается сервер,...

301
Передача сообщений между потоками - C#

Передача сообщений между потоками - C#

Есть у меня простой класс-логгер:

767
Поиск элемента по имени в WinForms

Поиск элемента по имени в WinForms

Мне надо на форме именно найти элемент (button, panel и тд

657