Очевидно, вы можете использовать |
(pipe?) для представления OR
, но есть ли способ представления AND
?
В частности, я хотел бы совместить абзацы текста, содержащие ВСЕ определенную фразу, но не в определенном порядке.
Очевидно, вы можете использовать |
(pipe?) для представления OR
, но есть ли способ представления AND
?
В частности, я хотел бы совместить абзацы текста, содержащие ВСЕ определенную фразу, но не в определенном порядке.
Используйте непотребляющее регулярное выражение.
Типичная (например, Perl/Java) нотация:
(?=
выражение )
Это означает "match expr, но после этого продолжить сопоставление в исходной точке совпадения".
Вы можете делать столько, сколько хотите, и это будет "и". Пример:
(?=match this expression)(?=match this too)(?=oh, and this)
Вы даже можете добавлять группы захвата внутри не потребляющих выражений, если вам нужно сохранить некоторые данные в нем.
Вам нужно использовать lookahead, как говорили некоторые из других респондентов, но в lookahead должны учитываться другие символы между его целевым словом и текущей совпадающей позицией. Например:
(?=.*word1)(?=.*word2)(?=.*word3)
.*
в первом lookahead позволяет ему сопоставлять любое количество символов, которое ему нужно, прежде чем оно попадет в "word1". Тогда позиция соответствия reset, а второй lookahead ищет слово "word2". reset снова, а заключительная часть соответствует "word3"; так как это последнее слово, которое вы проверяете, не обязательно, чтобы оно было в поиске, но это не повредило.
Чтобы соответствовать целому абзацу, вам необходимо привязать регулярное выражение с обоих концов и добавить окончательный .*
, чтобы использовать оставшиеся символы. Используя нотацию в стиле Perl, это будет:
/^(?=.*word1)(?=.*word2)(?=.*word3).*$/m
Модификатор 'm' предназначен для режима multline; он позволяет совпадению ^
и $
на границах абзаца ( "границы строк" в режиме регулярного выражения). В этом случае важно, чтобы вы не использовали модификатор 's', который позволяет метасимволу точек совпадать с символами новой строки, а также со всеми другими символами.
Наконец, вы хотите убедиться, что вы соответствуете целым словам, а не только фрагментам более длинных слов, поэтому вам нужно добавить границы слов:
/^(?=.*\bword1\b)(?=.*\bword2\b)(?=.*\bword3\b).*$/m
Посмотрите на этот пример:
У нас есть 2 регулярных выражения A и B, и мы хотим сопоставить их обоих, поэтому в псевдокоде это выглядит так:
pattern = "/A AND B/"
Его можно записать без использования оператора AND, например:
pattern = "/NOT (NOT A OR NOT B)/"
в PCRE:
"/(^(^A|^B))/"
regexp_match(pattern,data)
Вы можете сделать это с регулярным выражением, но, вероятно, вы захотите кого-то еще. Например, используйте несколько регулярных выражений и объедините их в условии if.
Вы можете перечислить все возможные перестановки со стандартным регулярным выражением, как это (соответствует a, b и c в любом порядке):
(abc)|(bca)|(acb)|(bac)|(cab)|(cba)
Однако это делает очень длинное и, вероятно, неэффективное регулярное выражение, если у вас более пары.
Если вы используете расширенную версию regexp, такую как Perl или Java, у них есть лучшие способы сделать это. Другие ответы предполагают использование положительной функции обзора.
Оператор AND неявный в синтаксисе RegExp.
Вместо этого оператор OR должен быть указан с помощью трубы.
Следующий RegExp:
var re = /ab/;
означает букву a
И письмо b
.
Он также работает с группами:
var re = /(co)(de)/;
это означает группу co
AND группу de
.
Замена (неявного) И с помощью OR потребует следующих строк:
var re = /a|b/;
var re = /(co)|(de)/;
Невозможно ли в вашем случае сделать AND на нескольких подходящих результатах? в псевдокоде
regexp_match(pattern1, data) && regexp_match(pattern2, data) && ...
Почему бы не использовать awk?
с awk regex AND, OR вопросы настолько просты
awk '/WORD1/ && /WORD2/ && /WORD3/' myfile
Если вы используете регулярные выражения Perl, вы можете использовать позитивный просмотр:
Например
(?=[1-9][0-9]{2})[0-9]*[05]\b
будет числом больше 100 и делится на 5
Вы можете передать свой вывод другому регулярному выражению. Используя grep, вы можете сделать это:
grep A | grep B
В дополнение к принятому ответу
Я предоставлю вам несколько практических примеров, которые помогут вам понять некоторые из вас. Например, скажем, у нас есть эти три строки текста:
[12/Oct/2015:00:37:29 +0200] // only this + will get selected
[12/Oct/2015:00:37:x9 +0200]
[12/Oct/2015:00:37:29 +020x]
Смотри демо здесь ДЕМО
Здесь мы хотим выбрать знак +, но только если он после двух чисел с пробелом и перед четырьмя цифрами. Это единственные ограничения. Мы бы использовали это регулярное выражение для достижения этого:
'~(?<=\d{2} )\+(?=\d{4})~g'
Обратите внимание: если вы разделите выражение, оно даст вам другие результаты.
Или, возможно, вы хотите выделить какой-то текст между тегами... но не тегами! Тогда вы можете использовать:
'~(?<=<p>).*?(?=<\/p>)~g'
для этого текста:
<p>Hello !</p> <p>I wont select tags! Only text with in</p>
Смотри демо здесь ДЕМО
Порядок всегда подразумевается в структуре регулярного выражения. Чтобы выполнить то, что вы хотите, вам придется сопоставлять входную строку несколько раз с различными выражениями.
То, что вы хотите сделать, невозможно с одним регулярным выражением.
Используйте AND вне регулярного выражения. В PHP оператор lookahead, похоже, не работал у меня, вместо этого я использовал этот
if( preg_match("/^.{3,}$/",$pass1) && !preg_match("/\s{1}/",$pass1))
return true;
else
return false;
Вышеупомянутое регулярное выражение будет соответствовать, если длина пароля составляет 3 или более символов, и в пароле нет пробелов.
Самый простой способ сделать это - это просто использовать два регулярных выражения, соединенных с логическим оператором and
, предоставленным вашим языком. В синтаксисе Perl это будет выглядеть так:
if ( /phrase 1/ and /phrase 2/ ) {
// it a match
}
Если вы хотите сделать одно и то же в одном регулярном выражении, вы всегда можете найти "фразу 1, за которой следует фраза 2" ИЛИ "фраза 2, за которой следует фраза 1"
if ( /phrase 1.*phrase 2|phrase 2.*phrase 1/ ) {
// it a match
}
Это будет очень сложно, если вы начнете добавлять фразы, но я бы не рекомендовал его для более длинных списков слов и фраз.