Regex pour “ET PAS” l'opération
Je suis à la recherche d'un général de la regex de construire afin de correspondre avec tout le motif x, à l'EXCEPTION des matchs de patron de y. C'est difficile à expliquer à la fois complète et concise...voir Matériel Nonimplication pour une définition formelle.
Par exemple, correspond à tout caractère de mot (\w
) à l'EXCEPTION de 'p'. Remarque je suis la soustraction d'un petit ensemble (la lettre 'p') à partir d'un ensemble plus large (tous les caractères de mot). Je ne peux pas juste dire [^p]
parce que ne pas prendre en compte la plus grande limitation de ne caractères de mot. Pour ce petit exemple, c'est sûr, je pourrais reconstruire manuellement quelque chose comme [a-oq-zA-OQ-Z0-9_]
, qui est une douleur, mais faisable. Mais je suis à la recherche d'un cadre plus général de construction de sorte qu'au moins le grand ensemble positif peut être une expression plus complexe. Comme match ((?<=(so|me|^))big(com?pl{1,3}ex([pA]t{2}ern)
sauf quand ça commence par "Mon".
Modifier: je me rends compte que c'était un mauvais exemple, car à l'exclusion des trucs au début ou à la fin est une situation où le négatif look-ahead et de recherche de derrière les expressions de travail. (Bohême-je encore vous a donné un upvote pour illustrer cette). Alors...à quoi au sujet de l'exclusion des matches qui contiennent "Mon" quelque part dans le milieu?...Je suis encore vraiment à la recherche d'une construction générale, comme une regex équivalent de la suite pseudo-sql
select [captures] from [input]
where (
input MATCHES [pattern1]
AND NOT capture MATCHES [pattern2]
)
Si la réponse est "il n'existe pas et voici pourquoi...", je voudrais savoir que trop.
Edit 2: Si je voulais définir ma propre fonction pour ce faire, il serait quelque chose comme (voici un C#, LINQ version):
public static Match[] RegexMNI(string input,
string positivePattern,
string negativePattern) {
return (from Match m in Regex.Matches(input, positivePattern)
where !Regex.IsMatch(m.Value, negativePattern)
select m).ToArray();
}
Je suis TOUJOURS demandais si il y est un natif de la regex de construire qui pourrait faire cela.
- Peut-être que vous pourriez accepter une réponse...
- Pas réellement répondu à la question. Ils ont tous obtenu coincé sur les détails de mon exemple, plutôt que de répondre à la question dans l'abstrait, mais complète. Les deux éditions de fournir la logique du concept clairement.
- Pour répondre à votre édité question, la solution générale "contient et ne contient pas B" est
^(?!.*B).*A
- Qu'est-ce que
?<=
? Je n'ai jamais vu cette expression avant, mais j'ai principalement fait du JavaScript, dont l'expression régulière de la langue n'est pas très expressif.
Vous devez vous connecter pour publier un commentaire.
Cela correspond à tout caractère qui est un mot et est pas un
p
:À résoudre votre exemple, utilisez une valeur négative de " look-ahead "Mon" n'importe où dans l'entrée, c'est à dire
(?!.*My)
:Note le point d'ancrage de départ de l'entrée
^
qui est nécessaire pour le faire fonctionner.Je me demande pourquoi les gens essaient de faire des choses compliquées dans les grandes monolithique des expressions régulières?
Pourquoi ne pouvez-vous pas juste décomposer le problème en sous-parties et à les rendre vraiment facile expressions régulières pour correspondre à ceux individuellement? Dans ce cas, le premier match
\w
, puis match[^p]
si ce premier match de la réussite. Perl (et autres langues) permet la construction de vraiment compliqué-à la recherche d'expressions régulières qui vous permet de faire exactement ce que vous devez faire dans une grande blobby-regex (ou, comme il peut l'être, avec un court et accrocheur crypto-regex), mais pour l'amour de celui qui a besoin de lire (et à entretenir!) le code une fois que vous êtes allé vous avez besoin de documenter pleinement. De mieux pour le rendre facile à comprendre dès le début.Désolé, tempêter plus.
Après vos modifications, il est toujours l'anticipation négatif, mais avec plus de quantificateur.
Si vous voulez vous assurer que l'ensemble de la chaîne ne contient pas de "Mon", puis vous pouvez faire ce
Voir ici sur Regexr
Cela correspond à toute séquence de caractères (avec le
.*
à la fin) et le(?!.*My).*
au début échoue lorsqu'il y a un "Mon" n'importe où dans la chaîne.Si vous voulez correspondent à rien de ce que si pas exactement "Mon", puis utiliser des ancres
Donc après en regardant à travers ces sujets, sur les RegEx: l'anticipation, lookbehind, la nidification, ET l'opérateur, la récursivité, les sous-programmes, les conditions, les ancres, et les groupes, je suis venu à la conclusion qu'il n'y est pas de solution qui répond à ce que vous me demandez.
La raison pour laquelle anticipation ne fonctionne pas c'est parce qu'il échoue dans ce cas simple:
Regex:
Matches:
Les trois premiers mots ne correspondent pas aux parce que Mon arrive après eux. Si "Mon" est à la fin de l'ensemble de la chaîne, vous ne serez jamais correspondre à rien parce que chaque d'anticipation échouent car ils vont tous voir.
Le problème semble être que, tout d'anticipation implicite d'ancrage de l'endroit où il commence son match, il n'y a aucun moyen de terminaison d'anticipation où se termine sa recherche avec une ancre basé sur le résultat d'une autre partie de l'expression régulière. Cela signifie que vous avez vraiment besoin de dupliquer tous les RegEx dans le négatif d'anticipation pour créer manuellement le point d'ancrage que vous êtes après.
C'est frustrant et une douleur. La "solution" semble être l'utilisation d'un langage de script pour effectuer deux regex est. L'une sur l'autre. Je suis surpris de ce type de fonctionnalité n'est pas mieux construite dans les moteurs d'expressions régulières.