J'ai la liste suivante d'éléments de dimension (pas complète, en réalité c'est beaucoup plus long):
Ktr_12345_180 Ktr_12345_160 Ktr_12345_1130 Kst_12345_180 Kst_12345_112 Kst_12345_120 Kst_12345_160
Mon objectif est de créer un sous-ensemble d'éléments dans Jedox 2019.1 Subset- Éditeur.
Le sous-ensemble doit inclure tous les éléments commençant par le préfixe "Ktr_"
sans avoir le suffixe _160
ou _180
I déjà construit un Regex (Ktr _) + [0-9] + (_ 180 | _160)
qui identifie les éléments que je ne veux pas.
Maintenant, je dois l'inverser. D'après ma connaissance, il n'y a pas de fonction native pour inverser une expression régulière, n'est-ce pas?
J'ai donc essayé de le faire en utilisant une anticipation négative: (Ktr _) + [0-9] + (? ! (_ 180 | _160))
Cela ne fonctionne pas du tout. J'ai essayé cela sous différentes formes, n'atteignant pas mon objectif ...
Je m'attends à ce que l'expression régulière fournisse les éléments voulus. Au lieu de cela, il montre simplement chaque élément ayant "Ktr_"
comme préfixe.
4 Réponses :
La bonne expression régulière dont vous avez besoin est la suivante,
\bKtr_[0-9]+_(?!1[68]0\b)[0-9]+\b
Ici, les limites de mots \ b
autour de l'expression régulière garantissent qu'elle ne donne pas une correspondance partielle dans un texte plus grand et (?! 1 [68] 0 \ b)
est l'anticipation négative requise pour rejeter les chaînes qui sont soit 160
ou 180
et le reste de le modèle est similaire au vôtre. De plus, à moins que vous n'ayez besoin d'un groupe, vous n'avez pas besoin d'écrire la première partie comme (Ktr _) +
et cela permettra également à Ktr_
tout cela une ou plusieurs fois, ce qui regarder vos échantillons ne pense pas que vous voulez. Je l'ai donc changé en simple Ktr_
uniquement mais au cas où c'était valide et effectivement nécessaire, conservez-le en remplaçant Krt_
par (Ktr _) +
Démo p>
Le problème est que +
n'est gourmand que dans la mesure où il sert tout le motif à faire correspondre; dans [0-9] +
il ne correspond pas à tous les chiffres suivants, mais seulement tous de sorte que le reste du modèle corresponde également .
Capturez la partie variable du motif ( [0-9] +
) et imprimez-la pour voir
/Ktr_[0-9]++(?!_180|_160)/
et nous obtenons
/Ktr_[0-9]+_(?!180|160)/
La correspondance 1234
laisse 5
pour satisfaire le lookahead "not _180" comme la prochaine chose après le 1234
.
Pour régler cela, nous avons besoin de détails sur les données et la question semble permettre deux possibilités
S'il y a toujours un _
suivant, comme le suggèrent des exemples de données, alors incluez simplement _
avant la recherche
got Ktr_1234 in Ktr_12345_180 got Ktr_12345 in Ktr_12345_1130 got Ktr_1234 in Ktr_12345_160
ce qui nécessite maintenant que tous les chiffres soient mis en correspondance avant _
. Cela "applique" également le _
là-bas
Si nous suivons ce que dit le texte
tous les éléments commençant par le préfixe "Ktr_" sans avoir le suffixe _160 ou _180
alors il se peut qu'il n'y ait rien après Ktr_12345
(par exemple), ou du moins pas un _
Dans ce cas, forcez uniquement la correspondance de tous les chiffres consécutifs
my @ary = qw( Ktr_12345_180 Ktr_12345_160 Ktr_12345_1130 Kst_12345_180 ); for (@ary) { say "got $1 in $_" if /(Ktr_[0-9]+)(?!_180|_160)/; }
où le +
supplémentaire fait correspondre autant que possible son sous-modèle précédent, indépendamment de ce qui suit plus loin dans le modèle entier; il porte le nom de quantificateurs possesifs
@ikegami Ah, mais bien sûr! Quelque chose me harcèle ... merci
Vous pouvez utiliser un quantificateur possessif avec un +
supplémentaire pour vous assurer que le [0-9] +
correspond à autant de chiffres qu'il y en a et n'essaye pas de revenir en arrière lorsque la correspondance échoue.
(Ktr_)+[0-9]++(?!(_180|_160))
Quantificateurs possessifs sont disponibles depuis Perl 5.10, ou avant avec la syntaxe sous-expression indépendante . p>
Une autre façon consiste à faire correspondre le modèle, puis à annuler le lookbehind négatif.
Essayez ceci
$ cat paul.txt Ktr_12345_180 Ktr_12345_160 Ktr_12345_1130 Kst_12345_180 Kst_12345_112 Kst_12345_120 Kst_12345_160 $ perl -lne ' print if /(Ktr_).+?(?<!_180|_160)\b/ ' paul.txt Ktr_12345_1130 $ perl -lne ' print if /(Ktr_)+[0-9]+.+?(?<!_180|_160)\b/ ' paul.txt Ktr_12345_1130 $