Выражение регулярного выражения с использованием границы слова для сопоставления буквенно-цифровых и не буквенно-цифровых символов в javascript

Я пытаюсь выделить набор ключевых слов с помощью JavaScript и регулярного выражения, я столкнулся с одной проблемой, мое ключевое слово может содержать буквальные и специальные символы, как в @text #number и т. Д. Я использую границу слова для сопоставления и замены всего слова, а не частичное слово (содержащееся в другом слове).

var pattern = new regex('\b '( + keyword +')\b',gi);

Здесь это выражение соответствует всем ключевым словам и выделяет их, однако в случае, если какое-либо ключевое слово, такое как "число:", не выделяется.

Мне известно, что \bword\b соответствует границе слова, а специальные символы не являются буквенно-цифровыми символами, следовательно, не соответствуют вышеуказанному выражению. Не могли бы вы сообщить мне, какое выражение регулярного выражения я могу использовать для выполнения вышеуказанного.

== Обновить ==

Для приведенного выше я попробовал предложение Тима Пицкера для следующего регулярного выражения,

expr: (?:^|\\b|\\s)(" + keyword + ")(?:$|\\b|\\s)

Вышеупомянутое, похоже, помогает мне найти совпадение для всего слова с буквенно-цифровыми и не буквенно-цифровыми символами, однако всякий раз, когда ключевое слово имеет последовательный тег html до или после ключевого слова без пробела, оно не выделяет это ключевое слово (например, социальное обеспечение < strong> * number: ‹br> *) Я пробовал следующее регулярное выражение, но оно заменяет тег html, предшествующий ключевому слову

expr: (?:^|\b|\s|<[^>]+>)number:(?:$|\b|\s|<[^>]+>) 

Здесь ключевое слово number:, которое имеет < br > (специально добавлено пробел для тега br, чтобы браузер не интерпретировал тег), следующее без пробела между ними выделяется ключевым словом.

Можете ли вы предложить выражение, которое игнорировало бы последовательный тег html для всего слова, содержащего как буквенно-цифровые, так и не буквенно-цифровые символы.


person Bhupen    schedule 18.11.2010    source источник
comment
Когда у вас есть определенное ключевое слово для поиска, почему вы хотите использовать регулярное выражение? Просто ищите слово как строку.   -  person Sebastian Schmidt    schedule 18.11.2010
comment
из tchrist ссылка ответ: см. этот ответ для тонких ошибок, связанных с использованием таких вещей, как \ b и \ B для границ.   -  person Félix Adriyel Gagnon-Grenier    schedule 14.05.2015


Ответы (6)


Итак, у вас есть две проблемы: JavaScript не поддерживает ретроспективный просмотр, а \b находит только границы между буквенно-цифровыми и не буквенно-цифровыми символами.

Первый вопрос: что именно составляет границу слова для ваших ключевых слов? Я предполагаю, что это должна быть либо \b граница, либо пробел. Если это так, вы можете поискать

"(?:^|\\b|\\s)(" + keyword + ")(?:$|\\b|\\s)"

Конечно, пробелы вокруг таких ключевых слов, как @number#, также станут частью соответствия, но, возможно, их выделение не является такой проблемой. В других случаях, т.е. е. если есть фактическая граница слова, которая может совпадать, пробелы не будут частью совпадения, поэтому в большинстве случаев это должно работать нормально.

Фактическое слово, которое вас интересует, будет в обратной ссылке №1, так что, если вы можете выделить его отдельно, даже лучше.

РЕДАКТИРОВАТЬ: если после / перед ключевым словом могут встречаться другие символы, кроме пробела, то я думаю, единственное, что вы можете сделать (если вы застряли с JavaScript):

  1. Убедитесь, что ваше ключевое слово начинается с символа alnum.
  2. Если это так, добавьте \b к вашему регулярному выражению.
  3. Убедитесь, что ваше ключевое слово заканчивается на символ alnum.
  4. Если это так, добавьте \b в ваше регулярное выражение.

Итак, для keyword используйте \bkeyword\b; для number: используйте \bnumber:; для @twitter используйте @twitter\b.

person Tim Pietzcker    schedule 18.11.2010
comment
похоже, что приведенное выше работает для того, чтобы найти соответствие для всего слова с буквенно-цифровыми и не буквенно-цифровыми символами, однако всякий раз, когда ключевое слово имеет последовательный тег html до или после ключевого слова, оно не выделяет это ключевое слово (например, номер социального страхования: ‹br ›). не могли бы вы сообщить мне, как мне игнорировать эти html-теги (могут быть любые)? Я пробовал следующее регулярное выражение, но оно заменяет html-тег, предшествующий ключевому слову - person Bhupen; 18.11.2010
comment
выражение: (?: ^ | \ b | \ s | ‹[^›] + ›) число: (?: $ | \ b | \ s |‹ [^ ›] +›) - person Bhupen; 18.11.2010

Нам нужно найти подстроку, которая имеет пробелы с обеих сторон. Если бы JavaScript поддерживал ретроспективный просмотр, это выглядело бы так:

var re = new RegExp('(?<!\\S)' + keyword + '(?!\\S)', 'gi');

Однако это не сработает (но будет работать с Perl и другими языками сценариев). Вместо этого нам нужно включить начальный пробельный символ (или начало строки) в качестве начальной части соответствия (и, при желании, зафиксировать то, что мы действительно ищем, в $ 1):

var re = new RegExp('(?:^|\\s)(' + keyword + ')(?!\\S)', 'gi');

Просто учтите, что реальное место, где начинается любое совпадение, будет на один символ после того, что возвращается свойством .index, возвращаемым re.exec(string), и что если вы обращаетесь к совпавшей строке, вам нужно либо удалить первый символ с помощью .slice(1), либо просто получить доступ к захваченному.

person PleaseStand    schedule 18.11.2010

может быть то, что ты пытаешься сделать, это

'\b\W*(' + keyword + ')\W*\b'
person Community    schedule 18.11.2010

Ваш ответ - взгляд вперед и назад: "(?=<[\s^])" + keyword + "(?=[\s$])". Биты в скобках не включаются в совпадение, поэтому включите любые символы, которые не разрешены в ключевых словах.

person Nathan MacInnes    schedule 18.11.2010
comment
К сожалению, моя ошибка ... JavaScript не поддерживает просмотр назад (хотя по какой-то причине он поддерживает просмотр вперед). Игнорировать. - person Nathan MacInnes; 18.11.2010

Как правильно указывает Тим, \b - сложные вещи, которые работают не так, как люди часто думают, что они работают. Прочтите этот ответ Подробнее об этом и о том, что вы можете с этим поделать.

Вкратце, это граница слева:

(?(?=\w)(?<!\w)|(?<!\W))

а это граница справа:

(?(?<=\w)(?!\w)|(?!\W))

Люди всегда думают, что есть пробелы, но это не так. Однако теперь, когда вы знаете настоящие определения, их легко встроить в них. Можно было заменить \w и \W на \s и \S в двух вышеприведенных шаблонах. Или можно было бы добавить понимание пробелов к блокам else.

person tchrist    schedule 18.11.2010

Попробуйте, это должно сработать ...

var pattern = new regex(@"\b"+Regex.escape(keyword)+@"\b",gi);
person sumair    schedule 09.09.2011