Регулярные выражения регулярных выражений - PullRequest
25 голосов
/ 12 августа 2010

Скажем, например, у меня есть следующая строка "one two(three) (three) four five", и я хочу заменить "(three)" на "(four)", но не в словах.Как мне это сделать?

В основном я хочу заменить регулярное выражение и получить следующую строку:

"one two(three) (four) four five"

Я пробовал следующее регулярное выражение, но оно не работает:

@"\b\(three\)\b"

По сути, я пишу некоторый код поиска и замены и даю пользователю обычные варианты для сопоставления регистра, совпадения с целым словом и т. Д. В этом случае пользователь выбрал совпадение с целыми словами, но я нене знаю, какой будет искомый текст.

Ответы [ 4 ]

55 голосов
/ 12 августа 2010

Ваша проблема связана с неправильным пониманием того, что на самом деле означает \b.По общему признанию, это не очевидно.

Причина, по которой \b\(three\)\b не соответствует тройкам в вашей входной строке, заключается в следующем:

  • \b означает: граница между символ слова и несловой символ .
  • Буквы (например, az) считаются символами слова .
  • Знаки пунктуациитакие метки, как ( считаются несловыми символами .

Здесь снова введена ваша входная строка, немного растянутая, и я отметил места, где \b соответствует:

 o n e   t w o ( t h r e e )   ( t h r e e )   f o u r   f i v e
↑     ↑ ↑     ↑ ↑         ↑     ↑         ↑   ↑       ↑ ↑       ↑

Как вы можете видеть здесь, между «двумя» и «(тремя)» есть \b, но не перед вторым «(тремя)».

Мораль этой истории?«Поиск по всему слову» не имеет особого смысла, если то, что вы ищете, это не просто слово (цепочка букв).Поскольку в строке поиска есть знаки препинания (скобки), это не является таким «словом».Если вы искали слово, состоящее только из символов слова , тогда \b будет делать то, что вы ожидаете.

Конечно, вы можете использовать другое регулярное выражение для соответствия строке, только еслион окружен пробелами или встречается в начале или конце строки:

(^|\s)\(three\)(\s|$)

Однако проблема в том, что если вы ищете «три» (без скобок),не найдет его в «(три)», потому что вокруг него нет пробелов, хотя на самом деле это целое слово.

Я думаю, что большинство текстовых редакторов (включая Visual Studio) будут использовать \b только если строка поиска фактически начинается и / или заканчивается символом слова:

var pattern = Regex.Escape(searchString);
if (Regex.IsMatch(searchString, @"^\w"))
    pattern = @"\b" + pattern;
if (Regex.IsMatch(searchString, @"\w$"))
    pattern = pattern + @"\b";

Таким образом, они найдут «(три)», даже если вы выберете «только целые слова».

4 голосов
/ 06 февраля 2014

Вот простой код, который может вас заинтересовать:

    string pattern = @"\b" + find + @"\b";
    Regex.Replace(stringToSearch, pattern, replace, RegexOptions.IgnoreCase);

Исходный код: snip2code - C #: заменить точное слово в предложении

0 голосов
/ 24 сентября 2013

Недавно я столкнулся с похожей проблемой в javascript, пытаясь сопоставить термины с ведущим символом '$' только как отдельные слова, например, если $ hot = 'FUZZ', то:

"some $hot $hotel bird$hot pellets" ---> "some FUZZ $hotel bird$hot pellets"

Регулярное выражение/\b\$hot\b/g (моё первое предположение) не сработало по той же причине, по которой паренсы не совпадали в исходном вопросе - в качестве несловесных символов нет границы слова / неслова, предшествующей им с пробелом или началом строки.*

Однако регулярное выражение /\B\$hot\b/g соответствует , что показывает, что позиции , а не , отмеченные в превосходном примере @ timwi, соответствуют термину \ B.Это не было интуитивно для меня, потому что ") (" не состоит из символов регулярных выражений.Но я предполагаю, что, поскольку \ B является инверсией класса \ b, это не обязательно должен быть символ слова, он должен быть просто символом, а не словом :)

0 голосов
/ 12 августа 2010

Как сказал Гопи, но (теоретически) ловит только (three) не two(three):

string input = "one two(three) (three) four five";

string output = input.Replace(" (three) ", " (four) ");

Когда я проверяю это, я получаю: "one two(three) (four) four five" Просто помните, что пробел - это строкахарактер тоже так его тоже можно заменить.Если бы я сделал это:

//use same input
string output = input.Replace(" ", ";");

я бы получил one;two(three);(three);four;five"

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