Подтвердить что ты не робот

Выражения выражения слова регулярного выражения

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

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

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

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

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

В основном я пишу код поиска и замены, и я даю пользователю обычные варианты соответствия case, match whole word и т.д. В этом случае пользователь решил совместить целые слова, но я не знаю, что текст поиск будет.

4b9b3361

Ответ 1

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

Причина \b\(three\)\b не соответствует тройкам в вашей строке ввода:

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

Вот ваша строка ввода снова, немного растянута, и Ive обозначил места, где \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 будет делать то, что вы ожидаете.

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

(^|\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";

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

Ответ 3

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

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

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

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

Ответ 4

Как сказал Гопи, но (теоретически) ловить только (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"