2015-08-15 4 views
3

Я пытаюсь исключить группу слов, но включает в себя другую группу слов в выражении qregexp, но в настоящее время у меня возникают проблемы с этим.Как исключить один набор слов, но включить другой в qregexp?

Вот некоторые из вещей, которые я пробовал (этот пример включены все слова):

(words|I|want|to|include)(?!the|ones|that|should|not|match) 

Так что я попробовал это (который не дал ничего):

^(words|I|want|to|include)(?:(?!the|ones|that|should|not|match).)*$ 

Могу ли я что-то отсутствует ?

Редактировать: причина, по которой мне нужно такое необычное регулярное выражение (include/exclude), заключается в том, что я хочу искать в серии статей и фильтровать те, которые содержат включенные в них слова, но нет, если они также имеют исключенные слова в них.

Так, например, если статья А:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. 

и статья Б:

Vivamus fermentum semper porta. 

Тогда регулярное выражение, которое включает в себя lorem бы фильтровать статью А, но не B. Но если ipsum является слово, которое я исключаю, я не хочу, чтобы статья А была отфильтрована.

Я рассмотрел возможность создания регулярных выражений, чтобы отфильтровывать статьи со словами, которые я хочу, а затем запускать второе регулярное выражение, исключая статьи из первого набора, которые я не хочу, но, к сожалению, используемое мной программное обеспечение не позволяет мне сделай это. Я могу запустить только одно регулярное выражение.

+0

Это не имеет смысла. Вы явно перечисляете слова, которые хотите сопоставить («включить»). После этого нет необходимости «исключать» что-либо; вы уже знаете, что находится в вашем «белом списке». – melpomene

+0

Что вы подразумеваете под включением? хотя бы одно слово из списка? –

+0

Я использую это программное обеспечение RSS (QuiteRSS), которое позволяет отфильтровывать статьи с использованием qregexp, которые содержат определенные слова. Тем не менее, я не хочу, чтобы статьи, содержащие эти слова, были отфильтрованы, если слова в негативном обзоре также содержатся в статье. – thequerist

ответ

2
^(?:(?!\b(?:the|ones|that|should|not|match)\b).)*\b(?:words|I|want|to|include)\b(?:(?!\b(?:the|ones|that|should|not|match)\b).)*$ 

Вам нужно добавить предпросмотр к обеим частям после поиска слов whcih должны match.See демо.

https://regex101.com/r/bK9wF1/3

или

^(?!.*\b(?:the|ones|that|should|not|match)\b)(?=.*\b(?:words|I|want|to|include)\b).*$ 

Добавить оба условия lookaheads .Увидь демо.

https://regex101.com/r/uF4oY4/60

1

Попробуйте это:

^(?:(?:(?!\b(?:the|ones|that|should|not|match)\b).|))*?\b(?:words|I|want|to|include)\b(?:(?:(?!\b(?:the|ones|that|should|not|match)\b).|))*$ 

Regular expression visualization

См Debuggex Demo (с согласующими и несовпадающими примерами).

Примечание. Вышеприведенное предполагает, что QRegExp поддерживает просмотр переменной длины - я этого не проверял.

Объяснение:

  1. Все слова должны быть точными (например, включать в себя «слово», но не «меч» или «слова»), так завернуты в \b с каждой стороны.
  2. Для слов, которые вы хотите включить его только те вопросы, которые по крайней мере, один из появляется по крайней мере один раз -. Так что это все, что разыскивается в не
  3. Ни одно из слов в списке исключения может появиться до или после поиск слова, поэтому для него нужна «группа исключений».
  4. Группы исключений реализованы с использованием метода, который очень хорошо объясняется в this answer.
  5. Первая группа исключений использует *?, чтобы сделать ее неживой, чтобы она не потребляла весь текст и не останавливалась, как только искомое слово найдено.
  6. Регулярное выражение завернуто в ^ ... $, чтобы гарантировать, что вся строка проверена/сопоставлена, а не только ее часть.
  7. Все группы помечены как группы, не захватывающие захват, с использованием ?: сразу же после первой скобки.
  8. Соответствие должно быть нечувствительным к регистру, поэтому регулярное выражение должно иметь соответствующий флаг для этого (например,/i).
3

Я думаю, что нет необходимости в закаленном жадном квантере. Используйте исключенные слова в качестве альтернатив внутри закрепленных негативных перспектив. Позвольте мне провести вас через это.

Вы говорите, что у вас есть Lorem ipsum dolor sit amet, consectetur adipiscing elit., и вы хотите, чтобы он совпал, так как содержит слово lorem. Регулярное выражение - \\blorem\\bQRegExp.CaseInsensitive установлено в 1), где \b используется для принудительного согласования всего слова. Чтобы предотвратить совпадение, если строка содержит слово ipsum, вам нужно использовать lookahead в самом начале строки.

^(?!.*\\bipsum\\b).*\\blorem\\b 

Теперь, it does not match the string in question.

Чтобы добавить больше альтернатив, мы можем использовать alternation operator |, и мы можем сделать это следующим образом: ^(?!.*\\b(?:words|to|exclude)\\b).*\\b(?:words|to|include)\\b. Обратите внимание на использование non-capturing groups, он не сохраняет захваченные тексты и потенциально повышает производительность по сравнению с группами захвата, которые сохраняют согласованный текст в буфере.

Таким образом, вы получаете

^(?!.*\\b(?:the|ones|that|should|not|match)\\b).*\\b(?:words|I|want|to|include)\\b 

См demo

Два замечания:

  1. На демо-сайте, одиночные обратные косые должны быть использованы, я удваивая их здесь QRegExp ,
  2. В Qt . в шаблоне сопоставляется любой символ, включая символ новой строки. На демонстрационном веб-сайте точка не соответствует символам новой строки. Вы можете заменить его на [^\n], если вам нужна такая же функциональность, но я думаю, что это необязательно.
2

Вы были так близки.Причина

^(words|I|want|to|include)(?:(?!the|ones|that|should|not|match).)*$ 

не работает, потому что это означает старт с одним из слов, которые я хочу, чтобы включить и продолжать сезам конец с вещами, которые не являются одним из слов, которые я не» t хотите включить. Чтобы исправить это, вы можете просто изменить начальную проверку использовать положительный предпросмотр:

^(?=.*(?:words|I|want|to|include))(?:(?!the|ones|that|should|not|match).)*$ 

Теперь это означает, что обеспечить что с самого начала Тиль какой-то момент, есть по крайней мере один из слов, которые я хотите включить, а затем продолжить, как в исходном регулярном выражении.

Чтобы сделать его еще более строгим, вы могли бы использовать word boundaries:

^(?=.*\b(?:words|I|want|to|include)\b)(?:(?!\b(?:the|ones|that|should|not|match)\b).)*$ 

Примечание, что это все чувствительно к регистру. Чтобы изменить это, вы можете использовать QRegExp::setCaseSensitivity

0

Упрощенная версия, что вам кажется, нужно:

^(?:(?!ipsum).)*(?:lorem)(?:(?!ipsum).)*$

Formatted:

^     # BOS 
(?: 
     (?! ipsum)   # Preceding text, but not these words 
     . 
)* 
(?: lorem)   # Text wanted 
(?: 
     (?! ipsum)   # Following text, but not these words 
     . 
)* 
$     # EOS