Вы имеете в виду, что вы хотите найти фразы в тексте, где каждая такая фраза является действительной перестановкой слов в данной фразе?
Ницше Джоу
2
Я помещаю это здесь, потому что три или четыре ответа игнорируют это. Lookahead не соответствует одинаковой длине для каждого предложения, если только они не заканчиваются на $. Один взгляд может соответствовать четырем символам, а другой 6. Например, (? = A *) (? = Aab) будет соответствовать aabaaaaba
Захари Вэнс
2
попробуйте использовать только символ «пробел» для оператора «И».
1 I'd like to match paragraphs of text. 2. Содержащие испорченный текст. Номер 1 открыт для интерпретации. Номер 2 можно сделать несколькими способами. Способ 1:, (?:(?:(?(1)(?!))\b(phrase1)\b.*?|(?(2)(?!))\b(phrase2)\b.*?)){2}Способ 2: (?=.*\bphrase1\b)(?=.*\bphrase2\b)где в этом случае соответствие абзаца в этом случае не определено, пока определение абзаца не будет формализовано.
Ответы:
385
Используйте непотребляющее регулярное выражение.
Типичная (т.е. Perl / Java) нотация:
(?=выраж)
Это означает «совпадение выражений, но после этого продолжайте сопоставление в исходной точке совпадения».
Вы можете сделать столько, сколько захотите, и это будет «и». Пример:
(?=match this expression)(?=match this too)(?=oh, and this)
Вы даже можете добавить группы захвата внутри непотребляющих выражений, если вам нужно сохранить в них некоторые данные.
Следует отметить, что этот конкретный пример называется положительным прогнозным утверждением. Он имеет иное применение, чем «и». Обратите внимание, что текст не используется.
Страгер
7
Использование (? =) Как это приводит к регулярному выражению, которое никогда не может быть успешным. Но это аналог конъюнкции к |. ОП просто ошибается в том, что, по его мнению, решит его проблему.
Можете ли вы добавить несколько простых примеров в коде perl в вашем ответе?
Питикос
343
Вы должны использовать lookahead, как сказали некоторые другие респонденты, но lookahead должен учитывать другие символы между его целевым словом и текущей позицией соответствия. Например:
(?=.*word1)(?=.*word2)(?=.*word3)
.*В первом опережающего просмотра позволяет ему соответствовать тем не менее много символов, которые необходимы , чтобы , прежде чем он попадает в «word1». Затем позиция совпадения сбрасывается, и второй ищущий ищет «word2». Сброс снова, и последняя часть соответствует «word3»; так как это последнее слово, которое вы проверяете, не обязательно, чтобы оно было в предвкушении, но это не повредит.
Чтобы соответствовать целому абзацу, необходимо закрепить регулярное выражение на обоих концах и добавить финал, .*чтобы использовать оставшиеся символы. Используя нотацию в стиле Perl, это будет:
/^(?=.*word1)(?=.*word2)(?=.*word3).*$/m
Модификатор 'm' предназначен для многострочного режима; это позволяет ^и $совпадать на границах абзаца ("границы строк" в регулярном выражении). В этом случае важно, чтобы вы не использовали модификатор 's', который позволяет метасимволу точки соответствовать символам новой строки и всем остальным символам.
Наконец, вы хотите убедиться, что вы соответствуете целым словам, а не только фрагментам более длинных слов, поэтому вам нужно добавить границы слов:
+1 для ясного и краткого ответа, демонстрирующего одно из лучших применений для поиска (в отличие от использования, такого как взлом для подсчета совпадения пароля в процентах). :)
zx81
1
@Liam :. MySQL использует разновидность POSIX ERE, поэтому нет. Он эффективно жертвует функциями в пользу производительности, что мне кажется разумным. Там больше информации здесь .
Алан Мур
3
замените .*на [\s\S]*в javascript, если у вас есть новые строки, так как .в движке javascript механизм регулярных выражений не соответствует новым строкам и не может быть
Уэсли Смит
41
Посмотрите на этот пример:
У нас есть 2 регулярных выражения A и B, и мы хотим сопоставить их обоих, поэтому в псевдокоде это выглядит так:
pattern ="/A AND B/"
Это можно записать без использования оператора AND следующим образом:
Это верно с точки зрения формальной логики, но здесь это абсолютно не поможет. В регулярных выражениях NOT может быть даже сложнее выразить, чем AND.
Алан Мур
@marvin_dpr У меня это работало в CMake, а другое предложение - (?=expr)нет. Кажется, это зависит от реализации.
Мелебиус
38
Не ^означает «начало строки» в синтаксисе регулярных выражений?
Лямбда Фея
3
В регулярных выражениях вообще ^отрицание только в начале класса символов. Если только CMake не делает что-то действительно прикольное (до такой степени, что называть их язык сопоставления с образцом "регулярным выражением" можно считать вводящим в заблуждение или неправильным), я предполагаю, что тот факт, что это сработало для вас, был изолированной случайностью.
tripleee
29
Вы можете сделать это с помощью регулярного выражения, но, вероятно, вы захотите к другому. Например, используйте несколько регулярных выражений и объедините их в предложении if.
Вы можете перечислить все возможные перестановки со стандартным регулярным выражением, например так (соответствует a, b и c в любом порядке):
(abc)|(bca)|(acb)|(bac)|(cab)|(cba)
Однако это делает очень длинное и, возможно, неэффективное регулярное выражение, если у вас более пары терминов.
Если вы используете какую-то расширенную версию регулярного выражения, такую как Perl или Java, у них есть лучшие способы сделать это. Другие ответы предложили использовать положительную прогнозную операцию.
Я не думаю, что ваш подход более неэффективен, чем 3 вида назад с их катастрофическим отступлением. Конечно, писать дольше, но учтите, что вы можете легко сгенерировать шаблон автоматически. Обратите внимание, что вы можете улучшить его, чтобы быстрее потерпеть неудачу a(bc|cb)|b(ac|ca)|c(ab|ba). И самое главное, вы можете использовать его с любым вкусом регулярных выражений.
Казимир и Ипполит
27
Оператор AND неявно присутствует в синтаксисе RegExp.
Вместо этого оператор OR должен быть указан с помощью канала.
Следующий RegExp:
var re =/ab/;
означает букву aи букву b.
Также работает с группами:
var re =/(co)(de)/;
это означает группу coИ группу de.
Замена (неявного) И на ИЛИ потребует следующих строк:
К сожалению, это не то, о чем просил ОП. Это находит что-нибудь в этом порядке, тогда как они хотели их в любом порядке. Проверьте ответ по stackoverflow.com/users/20938/alan-moore ниже, который является правильным.
ИЕСИ
1
@JESii, спасибо за вашу точку зрения, вы правы, и я неправильно понял вопрос из Hugoware, я сосредоточился на его первом предложении. Правильный ответ - правильное использование оператора lookahead, как писал AlanMoore. В любом случае, я думаю, что кто-то может найти мои разъяснения полезными, так как за них уже проголосовали, так что я бы не стал все выбрасывать. С уважением.
Эмануэле Дель Гранде
13
Разве в вашем случае невозможно выполнить AND для нескольких результатов сопоставления? в псевдокоде
Я нахожусь в ситуации, когда у меня есть некоторый код, который представляет собой таблицу данных правил, с единственной строкой соответствия шаблону регулярного выражения для проверки действительности правила. Переход к нескольким тестам - это не то, что я могу сделать в моем случае, и обычно в случаях других людей!
Алан Вулф
11
Почему бы не использовать awk?
с awk regex AND, OR все так просто
Здесь мы хотим выбрать знак +, но только если он после двух чисел с пробелом и до четырех. Это единственные ограничения. Мы бы использовали это регулярное выражение для достижения этого:
'~(?<=\d{2} )\+(?=\d{4})~g'
Обратите внимание, что если вы отделите выражение, оно даст вам другие результаты.
Или, возможно, вы хотите выделить какой-то текст между тегами ... но не тегами! Тогда вы можете использовать:
'~(?<=<p>).*?(?=<\/p>)~g'
для этого текста:
<p>Hello !</p><p>I wont select tags! Only text with in</p>
Какой ответ был принят? Пожалуйста, добавьте ссылку на него для будущего меня.
Джеймс Браун
6
Порядок всегда подразумевается в структуре регулярного выражения. Чтобы выполнить то, что вы хотите, вам придется сопоставлять входную строку несколько раз с различными выражениями.
То , что вы хотите сделать , это не возможно с одним регулярным выражением.
Это технически невозможно, но не стоит реализовывать. Я не знаю, почему кто-то проголосовал, хотя ...
Роберт Р
13
Вероятно потому, что это не только возможно, но и просто, если предположить, что ваш regex-артикль поддерживает прогнозирование. И это хорошая ставка; большинство современных языков программирования поддерживают их.
Алан Мур
3
Используйте AND вне регулярного выражения. В PHP оператор lookahead, похоже, не работает для меня, вместо этого я использовал это
I'd like to match paragraphs of text
. 2. Содержащие испорченный текст. Номер 1 открыт для интерпретации. Номер 2 можно сделать несколькими способами. Способ 1:,(?:(?:(?(1)(?!))\b(phrase1)\b.*?|(?(2)(?!))\b(phrase2)\b.*?)){2}
Способ 2:(?=.*\bphrase1\b)(?=.*\bphrase2\b)
где в этом случае соответствие абзаца в этом случае не определено, пока определение абзаца не будет формализовано.Ответы:
Используйте непотребляющее регулярное выражение.
Типичная (т.е. Perl / Java) нотация:
(?=
выраж)
Это означает «совпадение выражений, но после этого продолжайте сопоставление в исходной точке совпадения».
Вы можете сделать столько, сколько захотите, и это будет «и». Пример:
(?=match this expression)(?=match this too)(?=oh, and this)
Вы даже можете добавить группы захвата внутри непотребляющих выражений, если вам нужно сохранить в них некоторые данные.
источник
Вы должны использовать lookahead, как сказали некоторые другие респонденты, но lookahead должен учитывать другие символы между его целевым словом и текущей позицией соответствия. Например:
.*
В первом опережающего просмотра позволяет ему соответствовать тем не менее много символов, которые необходимы , чтобы , прежде чем он попадает в «word1». Затем позиция совпадения сбрасывается, и второй ищущий ищет «word2». Сброс снова, и последняя часть соответствует «word3»; так как это последнее слово, которое вы проверяете, не обязательно, чтобы оно было в предвкушении, но это не повредит.Чтобы соответствовать целому абзацу, необходимо закрепить регулярное выражение на обоих концах и добавить финал,
.*
чтобы использовать оставшиеся символы. Используя нотацию в стиле Perl, это будет:Модификатор 'm' предназначен для многострочного режима; это позволяет
^
и$
совпадать на границах абзаца ("границы строк" в регулярном выражении). В этом случае важно, чтобы вы не использовали модификатор 's', который позволяет метасимволу точки соответствовать символам новой строки и всем остальным символам.Наконец, вы хотите убедиться, что вы соответствуете целым словам, а не только фрагментам более длинных слов, поэтому вам нужно добавить границы слов:
источник
.*
на[\s\S]*
в javascript, если у вас есть новые строки, так как.
в движке javascript механизм регулярных выражений не соответствует новым строкам и не может бытьПосмотрите на этот пример:
У нас есть 2 регулярных выражения A и B, и мы хотим сопоставить их обоих, поэтому в псевдокоде это выглядит так:
Это можно записать без использования оператора AND следующим образом:
в PCRE:
источник
(?=expr)
нет. Кажется, это зависит от реализации.^
означает «начало строки» в синтаксисе регулярных выражений?^
отрицание только в начале класса символов. Если только CMake не делает что-то действительно прикольное (до такой степени, что называть их язык сопоставления с образцом "регулярным выражением" можно считать вводящим в заблуждение или неправильным), я предполагаю, что тот факт, что это сработало для вас, был изолированной случайностью.Вы можете сделать это с помощью регулярного выражения, но, вероятно, вы захотите к другому. Например, используйте несколько регулярных выражений и объедините их в предложении if.
Вы можете перечислить все возможные перестановки со стандартным регулярным выражением, например так (соответствует a, b и c в любом порядке):
Однако это делает очень длинное и, возможно, неэффективное регулярное выражение, если у вас более пары терминов.
Если вы используете какую-то расширенную версию регулярного выражения, такую как Perl или Java, у них есть лучшие способы сделать это. Другие ответы предложили использовать положительную прогнозную операцию.
источник
a(bc|cb)|b(ac|ca)|c(ab|ba)
. И самое главное, вы можете использовать его с любым вкусом регулярных выражений.Оператор AND неявно присутствует в синтаксисе RegExp.
Вместо этого оператор OR должен быть указан с помощью канала.
Следующий RegExp:
означает букву
a
и буквуb
.Также работает с группами:
это означает группу
co
И группуde
.Замена (неявного) И на ИЛИ потребует следующих строк:
источник
Разве в вашем случае невозможно выполнить AND для нескольких результатов сопоставления? в псевдокоде
источник
Почему бы не использовать awk?
с awk regex AND, OR все так просто
источник
Если вы используете регулярные выражения Perl, вы можете использовать положительный взгляд:
Например
будет число больше 100 и делится на 5
источник
Вы могли бы передать свой вывод другому регулярному выражению. Используя grep, вы можете сделать это:
grep A | grep B
источник
В дополнение к принятому ответу
Я приведу вам несколько практических примеров, которые помогут вам понять некоторые из вас. Например, допустим, у нас есть эти три строки текста:
Посмотреть демо здесь DEMO
Здесь мы хотим выбрать знак +, но только если он после двух чисел с пробелом и до четырех. Это единственные ограничения. Мы бы использовали это регулярное выражение для достижения этого:
Обратите внимание, что если вы отделите выражение, оно даст вам другие результаты.
Или, возможно, вы хотите выделить какой-то текст между тегами ... но не тегами! Тогда вы можете использовать:
для этого текста:
Посмотреть демо здесь DEMO
источник
Порядок всегда подразумевается в структуре регулярного выражения. Чтобы выполнить то, что вы хотите, вам придется сопоставлять входную строку несколько раз с различными выражениями.
То , что вы хотите сделать , это не возможно с одним регулярным выражением.
источник
Используйте AND вне регулярного выражения. В PHP оператор lookahead, похоже, не работает для меня, вместо этого я использовал это
Приведенное выше регулярное выражение будет соответствовать, если длина пароля составляет 3 символа или более и в нем нет пробелов.
источник