2
votes

Création d'un sous-ensemble à l'aide d'une expression régulière

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.


0 commentaires

4 Réponses :


0
votes

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>


0 commentaires

5
votes

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


1 commentaires

@ikegami Ah, mais bien sûr! Quelque chose me harcèle ... merci



0
votes

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>


0 commentaires

1
votes

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
$


0 commentaires