Регулярные выражения: есть ли оператор И?

Очевидно, вы можете использовать | (pipe?) для представления OR, но есть ли способ представления AND?

В частности, я хотел бы совместить абзацы текста, содержащие ВСЕ определенную фразу, но не в определенном порядке.

Ответ 1

Используйте непотребляющее регулярное выражение.

Типичная (например, Perl/Java) нотация:

(?= выражение )

Это означает "match expr, но после этого продолжить сопоставление в исходной точке совпадения".

Вы можете делать столько, сколько хотите, и это будет "и". Пример:

(?=match this expression)(?=match this too)(?=oh, and this)

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

Ответ 2

Вам нужно использовать 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

Ответ 3

Посмотрите на этот пример:

У нас есть 2 регулярных выражения A и B, и мы хотим сопоставить их обоих, поэтому в псевдокоде это выглядит так:

pattern = "/A AND B/"

Его можно записать без использования оператора AND, например:

pattern = "/NOT (NOT A OR NOT B)/"

в PCRE:

"/(^(^A|^B))/"

regexp_match(pattern,data)

Ответ 4

Вы можете сделать это с регулярным выражением, но, вероятно, вы захотите кого-то еще. Например, используйте несколько регулярных выражений и объедините их в условии if.

Вы можете перечислить все возможные перестановки со стандартным регулярным выражением, как это (соответствует a, b и c в любом порядке):

(abc)|(bca)|(acb)|(bac)|(cab)|(cba)

Однако это делает очень длинное и, вероятно, неэффективное регулярное выражение, если у вас более пары.

Если вы используете расширенную версию regexp, такую ​​как Perl или Java, у них есть лучшие способы сделать это. Другие ответы предполагают использование положительной функции обзора.

Ответ 5

Оператор 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)/;

Ответ 6

Невозможно ли в вашем случае сделать AND на нескольких подходящих результатах? в псевдокоде

regexp_match(pattern1, data) && regexp_match(pattern2, data) && ...

Ответ 7

Почему бы не использовать awk?
с awk regex AND, OR вопросы настолько просты

awk '/WORD1/ && /WORD2/ && /WORD3/' myfile

Ответ 8

Если вы используете регулярные выражения Perl, вы можете использовать позитивный просмотр:

Например

(?=[1-9][0-9]{2})[0-9]*[05]\b

будет числом больше 100 и делится на 5

Ответ 9

Вы можете передать свой вывод другому регулярному выражению. Используя grep, вы можете сделать это:

grep A | grep B

Ответ 10

В дополнение к принятому ответу

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

[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> 

Смотри демо здесь ДЕМО

Ответ 11

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

То, что вы хотите сделать, невозможно с одним регулярным выражением.

Ответ 12

Используйте AND вне регулярного выражения. В PHP оператор lookahead, похоже, не работал у меня, вместо этого я использовал этот

if( preg_match("/^.{3,}$/",$pass1) && !preg_match("/\s{1}/",$pass1))
    return true;
else
    return false;

Вышеупомянутое регулярное выражение будет соответствовать, если длина пароля составляет 3 или более символов, и в пароле нет пробелов.

Ответ 13

Самый простой способ сделать это - это просто использовать два регулярных выражения, соединенных с логическим оператором 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
}

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