В JavaScript, как я могу использовать регулярное выражение для соответствия, если слова не входят в список исключенных слов?
Как использовать регулярное выражение для соответствия любому слову (\ w), за исключением списка определенных слов? Например:
Я хочу совместить слова use
и utilize
и любые слова после него, кроме слов something
или fish
.
use this <-- match
utilize that <-- match
use something <-- don't want to match this
utilize fish <-- don't want to match this
Как указать список слов, с которыми я не хочу сопоставлять?
Ответы
Ответ 1
Вы можете использовать отрицательный lookahead, чтобы определить, что слово, которое вы собираетесь сопоставить, не является чем-то особенным. Для этого можно использовать следующее регулярное выражение:
(use|utilize)\s(?!fish|something)(\w+)
Это будет соответствовать "использовать" или "использовать", за которым следует пробел, а затем, если следующее слово не "рыба" или "что-то", оно будет соответствовать следующему слову.
Ответ 2
Это должно сделать это:
/(?:use|utilize)\s+(?!something|fish)\w+/
Ответ 3
Не жестко задавайте регулярные выражения
Вместо того, чтобы ставить все условия поиска и исключения в единое строго жесткое кодированное регулярное выражение, он часто более удобен (и, конечно, читается), использовать оценку короткого замыкания для выбора строк, соответствующих желаемым условиям, а затем отклонять строки, содержащие нежелательные термины.
Затем вы можете инкапсулировать это тестирование в функцию, которая возвращает логическое значение, основанное на значениях времени выполнения ваших массивов. Например:
'use strict';
// Join arrays of terms with the alternation operator.
var searchTerms = new RegExp(['use', 'utilize'].join('|'));
var excludedTerms = new RegExp(['fish', 'something'].join('|'));
// Return true if a string contains only valid search terms without any
// excluded terms.
var isValidStr = function (str) {
return (searchTerms.test(str) && !excludedTerms.test(str));
};
isValidStr('use fish'); // false
isValidStr('utilize hammer'); // true
Ответ 4
Некоторые люди, столкнувшись с проблемой, думают: "Я знаю, я буду использовать регулярные выражения.
Теперь у них есть две проблемы.
Регулярные выражения подходят для соответствия регулярным последовательностям символов, а не слов. Любой лексер + парсер будет гораздо более подходящим. Например, грамматика для этой задачи будет выглядеть очень просто в Antlr. Если вы не можете позволить себе кривую обучения за лексерами/парсерами (они довольно легки для вашей заданной задачи), то разделение текста на слова с регулярным выражением, а затем простого поиска с опережением 1 будет достаточно.
Регулярные выражения со словами очень сложны очень быстро. Их трудно читать и трудно выполнять.
Обновление:
Спасибо за все downvotes. Вот пример того, что я имел в виду.
import re
def Tokenize( text ):
return re.findall( "\w+", text )
def ParseWhiteListedWordThenBlackListedWord( tokens, whiteList, blackList ):
for i in range( 0, len( tokens ) - 1 ):
if tokens[i] in whiteList and tokens[i + 1] not in blackList:
yield ( tokens[i], tokens[i + 1] )
Вот несколько тестов производительности:
>>> timeit.timeit( 'oldtime()', 'from __main__ import oldtime', number=1 )
0.02636446265387349
>>> timeit.timeit( 'oldtime()', 'from __main__ import oldtime', number=1000 )
28.80968123656703
>>> timeit.timeit( 'newtime()', 'from __main__ import newtime', number=100 )
44.24506212427741
>>> timeit.timeit( 'newtime11()', 'from __main__ import newtime11', number=1 ) +
timeit.timeit( 'newtime13()', 'from __main__ import newtime13', number=1000 )
103.07938725936083
>>> timeit.timeit( 'newtime11()', 'from __main__ import newtime11', number=1 ) +
timeit.timeit( 'newtime12()', 'from __main__ import newtime12', number=1000 )
0.3191265909927097
Некоторые примечания:
тестирование было проведено над английским текстом "Pride anf Prejudice" Джейн Остин, первые слова были "Mr" и "my", вторыми словами были "Bennet" и "дорогие".
oldtime() является регулярным выражением.
newtime() является Tokenizer + Parser, помните, что он выполнялся 100 раз, а не 1000, поэтому сопоставимое время для этого было бы ~ 442.
Следующие два теста предназначены для имитации повторных прогонов Parser над одним и тем же текстом, поскольку вы повторно используете результаты Tokenizer.
newtime11() - только токенизатор.
newtime13() - это Parser с результатами, преобразованными в список (для имитации обхода результатов).
newtime12() - это просто Parser.
Ну, регулярные выражения быстрее, довольно много в случае одного прохода, даже в случае генератора (основная часть времени тратится на токенизацию текста, в случае Tokenizer + Parser). Но выражения генератора чрезвычайно быстры, когда вы можете повторно использовать токенырованный текст и оценивать результаты парсера лениво.
Существует довольно небольшая оптимизация производительности, но это усложнит решение, возможно, до тех пор, пока регулярные выражения не станут лучшей реализацией.
Подход токенизатора + парсера имеет как преимущества, так и недостатки:
- структура решения сложнее (больше элементов), но каждый элемент проще
- элементы легко тестируются, включая автоматическое тестирование
- он медленный, но он становится лучше, повторно используя один и тот же текст и оценивая результаты лениво
- из-за генераторов и ленивой оценки, некоторые работы можно избежать
- тривиально менять белый список и/или черный список
- тривиально иметь несколько белых списков, несколько черных списков и/или их комбинации
- тривиально добавлять новые парсеры, повторно использующие результаты токенизатора
Теперь к тому тернному Тебе, который тебе нужен, вопрос. Вам не понадобится решение первоначального вопроса, если только он не является частью более крупной задачи. И эта более важная задача должна диктовать лучший подход.
Обновление: есть хорошее обсуждение regualr-выражений в лексинге и синтаксическом анализе на http://commandcenter.blogspot.ru/2011/08/regular-expressions-in-lexing-and.html, Я обобщу его с цитатой
Поощрение регулярных выражений как панацеи для всей обработки текста проблемы - это не только ленивая и плохая инженерия, но и усиливает их использование людьми, которые не должны их использовать.