Question Expressions régulières: Existe-t-il un opérateur AND?


De toute évidence, vous pouvez utiliser le | (pipe?) pour représenter OR, mais y a-t-il un moyen de représenter AND ainsi que?

Plus précisément, je voudrais faire correspondre des paragraphes de texte qui contiennent TOUTES une certaine expression, mais sans ordre particulier.


527
2018-01-22 16:49


origine


Réponses:


Utilisez une expression régulière non consommatrice.

La notation typique (c'est-à-dire Perl / Java) est:

(?=expr)

Cela signifie "correspondre expr mais après cela continuer à correspondre au point de match original. "

Vous pouvez en faire autant que vous le souhaitez, et ce sera un "et". Exemple:

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

Vous pouvez même ajouter des groupes de capture à l'intérieur des expressions non consommatrices si vous avez besoin d'en sauvegarder certaines données.


310
2018-01-22 16:58



Vous devez utiliser lookahead comme l'ont dit d'autres répondeurs, mais le lookahead doit tenir compte des autres caractères entre son mot cible et la position de correspondance actuelle. Par exemple:

(?=.*word1)(?=.*word2)(?=.*word3)

le .* dans le premier lookahead, il permet de faire correspondre autant de caractères qu'il le faut avant d'arriver à "word1". Ensuite, la position de correspondance est réinitialisée et le second lookahead recherche "word2". Réinitialiser à nouveau, et la partie finale correspond à "word3"; puisque c'est le dernier mot que vous vérifiez, il n'est pas nécessaire que ce soit dans une tête de lecture, mais cela ne fait pas de mal.

Afin de correspondre à un paragraphe entier, vous devez ancrer l'expression régulière aux deux extrémités et ajouter une finale .* pour consommer les caractères restants. En utilisant la notation de style Perl, ce serait:

/^(?=.*word1)(?=.*word2)(?=.*word3).*$/m

Le modificateur 'm' est pour le mode multline; ça laisse le ^ et $ correspond aux limites de paragraphe ("limites de ligne" dans regex-speak). Il est essentiel dans ce cas que vous ne pas utilisez le modificateur 's', qui permet au métacaractère de point de correspondre aux nouvelles lignes ainsi qu'à tous les autres caractères.

Enfin, vous voulez vous assurer que vous faites correspondre des mots entiers et pas seulement des fragments de mots plus longs, vous devez donc ajouter des limites de mots:

/^(?=.*\bword1\b)(?=.*\bword2\b)(?=.*\bword3\b).*$/m

270
2018-01-22 20:04



Regardez cet exemple:

Nous avons 2 regexps A et B et nous voulons faire correspondre les deux, donc dans le pseudo-code il ressemble à ceci:

pattern = "/A AND B/"

Il peut être écrit sans utiliser l'opérateur AND comme ceci:

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

dans PCRE:

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

regexp_match(pattern,data)

27
2018-04-20 12:11



Vous pouvez le faire avec une expression régulière, mais vous aurez probablement besoin d'autre chose. Par exemple, utilisez plusieurs expressions rationnelles et combinez-les dans une clause if.

Vous pouvez énumérer toutes les permutations possibles avec une expression rationnelle standard, comme ceci (correspond à a, b et c dans n'importe quel ordre):

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

Cependant, cela rend une expression rationnelle très longue et probablement inefficace, si vous avez plus que des termes de couple.

Si vous utilisez une version étendue de regexp, comme Perl ou Java, ils ont de meilleures façons de le faire. D'autres réponses ont suggéré d'utiliser une opération d'anticipation positive.


22
2018-01-22 18:07



L'opérateur AND est implicite dans la syntaxe RegExp.
L'opérateur OR doit plutôt être spécifié avec un tuyau.
Le RegExp suivant:

var re = /ab/;

signifie la lettre a  ET la lettre b.
Il fonctionne également avec des groupes:

var re = /(co)(de)/;

cela signifie le groupe co  ET le groupe de.
Remplacer le AND (implicite) avec un OU nécessiterait les lignes suivantes:

var re = /a|b/;
var re = /(co)|(de)/;

11
2018-06-30 11:25



Pourquoi ne pas utiliser awk?
avec awk regex ET, OU questions est si simple

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

9
2017-12-27 13:49



N'est-il pas possible dans votre cas de faire l'ET sur plusieurs résultats correspondants? en pseudocode

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

8
2018-01-22 16:57



Si vous utilisez des expressions régulières Perl, vous pouvez utiliser lookahead positif:

Par exemple

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

serait des nombres supérieurs à 100 et divisibles par 5


8
2018-01-22 16:59



Vous pouvez rediriger votre sortie vers une autre regex. En utilisant grep, vous pouvez faire ceci:

grep A | grep B


6
2017-11-20 21:36



En plus de la réponse acceptée 

Je vais vous fournir quelques exemples pratiques qui vous aideront à mieux comprendre les choses. Par exemple, disons que nous avons ces trois lignes de texte:

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

Voir la démo ici  DEMO

Ce que nous voulons faire ici est de sélectionner le signe + mais seulement si c'est après deux nombres avec un espace et si c'est avant quatre nombres. Ce sont les seules contraintes. Nous utiliserions cette expression régulière pour y parvenir:

'~(?<=\d{2} )\+(?=\d{4})~g'

Notez que si vous séparez l'expression, vous obtiendrez des résultats différents.

Ou peut-être que vous voulez sélectionner du texte entre les balises ... mais pas les balises! Ensuite, vous pouvez utiliser:

'~(?<=<p>).*?(?=<\/p>)~g'

pour ce texte:

<p>Hello !</p> <p>I wont select tags! Only text with in</p> 

Voir la démo ici  DEMO


2
2017-11-13 11:30



Utilisez ET en dehors de l'expression régulière. En PHP lookahead opérateur ne semblait pas fonctionner pour moi, à la place j'ai utilisé cette

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

L'expression régulière ci-dessus correspondra si la longueur du mot de passe est de 3 caractères ou plus et s'il n'y a pas d'espaces dans le mot de passe.


0
2017-09-09 18:13