Regex Замените целые слова пунктуацией [duplicate]

Я читал эти ответы несколько раз, но НЕ ДЕЙСТВИТЕЛЬНО добирался до тех пор, пока не узнал о техническом определении «Вызов путем совместного использования» , как это называется Барбарой Лисков

Семантика вызова путем совместного использования отличается от вызова по ссылке в том, что назначения для аргументов функции внутри функции не отображаются вызывающему (в отличие от ссылочной семантики) [например, если переменная была передана, невозможно смоделировать присвоение этой переменной в области вызывающего. Однако, поскольку функция имеет доступ к тому же объекту, что и вызывающий (без копирования), мутации для этих объектов, если объекты изменяемы, внутри функции видны вызывающему, которые могут отличаться от вызова по значению семантика. Мутации изменяемого объекта внутри функции видны вызывающему, потому что объект не копируется и не клонируется - он является общим.

То есть, ссылки на параметры изменяются, если вы идете и получаете доступ к самого параметра. С другой стороны, назначение параметра исчезает после оценки и не доступно для вызывающего функции.

24
задан CroweMan 12 August 2010 в 14:32
поделиться

4 ответа

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

Вы можете, конечно, использовать другое 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";

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

51
ответ дан Timwi 21 August 2018 в 06:43
поделиться
  • 1
    Возможно, это не имеет смысла, но я хотел бы, чтобы он работал. У вас есть идеи, как я могу это сделать? В основном я хотел бы подражать функции поиска и замены в visual studio. – CroweMan 12 August 2010 в 14:46
  • 2
    @CroweMan: Вы противоречите себе. Вы сказали: «Я не хочу» двух (трех) ». для замены ", но Visual Studio делает это. – Timwi 12 August 2010 в 14:52
  • 3
    Большое спасибо. Ты звезда! – CroweMan 12 August 2010 в 14:55
  • 4
    Пожалуйста, будьте осторожны границ стиля \b. – tchrist 18 November 2010 в 17:18

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

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

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

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

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

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

-1
ответ дан AllenG 21 August 2018 в 06:43
поделиться
  • 1
    Проблема в том, что пользователь вводит текст в поле поиска и замены, и они выбрали «соответствовать целым словам». Поэтому мне нужно использовать что-то интеллектуальное, как регулярные выражения, и я не могу просто добавить & quot; & Quot; до или после выражения, поскольку обработка символа может быть «,» или что-то еще – CroweMan 12 August 2010 в 14:45

Здесь вам может быть интересен простой код:

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

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

4
ответ дан Dominique Terrs 21 August 2018 в 06:43
поделиться

Недавно я столкнулся с аналогичной проблемой в javascript, пытаясь сопоставить термины с ведущим символом $, только как отдельные слова, например. if $ 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, он не должен быть символами слов, он просто должен быть несловными символами:)

0
ответ дан jongala 21 August 2018 в 06:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: