9
votes

Quelle expression régulière peut supprimer des éléments en double d'une chaîne?

Compte tenu d'une chaîne d'identificateurs séparés par : , est-il possible de construire une expression régulière pour extraire les identifiants uniques dans une autre chaîne, également séparé par : ?

Comment est-il possible de réaliser cela en utilisant une expression régulière? J'ai essayé S / (: [^:]) (. *) \ 1/1 $ 1 $ 2 / g sans chance, car le (. *) Est gourmand et saute au dernier match de 1 $ .

Exemple: A: B: C: D: C: C: X: C: C: E: E: F Devrait donner A: B: C: D: X: E: F

note: je codent à Perl, mais j'apprécie beaucoup d'utiliser une regex pour cela.


1 commentaires

Pourriez-vous s'il vous plaît afficher un exemple de ce que vous recherchez, je ne comprends pas tout à fait.


5 Réponses :



0
votes

Si les identificateurs sont triés, vous pourrez peut-être le faire en utilisant Lookahead / LookbeHind. S'ils ne sont pas, alors cela dépasse la puissance de calcul d'une regex. Maintenant, juste parce qu'il est impossible avec une regex formelle ne signifie pas qu'il est impossible si vous utilisez une fonction de regex spécifique à Perl, mais si vous souhaitez conserver vos regex portables, vous devez décrire cette chaîne dans une langue prenant en charge les variables.


3 commentaires

Le tri n'est pas pertinent, voir ma solution.


Qu'entendez-vous par les fonctionnalités spécifiques à Perl? Les groupes de capture, les rafraîchissements, les frontières des mots et les lunettes de vue sont très largement pris en charge. Parmi les caractéristiques utilisées dans cette discussion, le seul que j'appellerais non-portable est l'apparence des regards, surtout des regards sans bornes.


@Tim: Je dirais que cela est pertinent dans le sens où, si les identifiants ont été triés, éliminer les doublons serait trivial: s / (\ w +) (: \ 1) + (? =: | $) / $ 1 / g



1
votes
a:b:c:d:x:e:f

1 commentaires

+1 Pour vides pendant que la boucle, même si je pense qu'une solution plus complète pourrait être: pendant {$ str = ~ s / (: [^:] + | [^:] + :) \ 1 ( . *) / 1 $ 2 $ 3 / g} Pour vérifier la première lettre.



10
votes

in .NET qui prend en charge une répétition infinie à l'intérieur de Lookebehind, vous pouvez rechercher xxx pré>

et remplacer toutes les correspondances avec la chaîne vide. p>

Perl (au moins Perl 5 ) seulement prend en charge les regards de look longueur fixe, de sorte que vous pouvez essayer ce qui suit (à l'aide de regards Lookahead, avec un résultat subtilement différent): p> xxx pré>

Si vous remplacez cela avec la chaîne vide, tout Précédent em> Les répétitions d'une entrée en double seront supprimées; Le dernier em> sera restent. Donc au lieu de p> xxx pré>

, vous obtiendrez p> xxx pré>

si c'est correct, vous pouvez utiliser p>

$subject =~ s/\b(\w+):(?=.*\b\1:?)//g;


6 commentaires

L'ordre de sortie n'est pas pertinent pour moi, c'est pourquoi je ne l'ai pas mentionné dans la question (peut-être que j'aurais dû dire que c'était sans importance :). Merci, ça a fonctionné comme un charme!


Veuillez mettre à jour votre réponse, la solution que vous avez fournie ne fonctionne que si les mots étaient un caractère long. Oublié de mentionner cela aussi. Une meilleure réponse serait s / \ b (\ w +): (? =. * \ 1:?) // g


@Tom: Excellent point. J'ai mis à jour ma réponse. Le mot affirmation des limites est également nécessaire devant la déférence.


Avez-vous testé cela .NET Regex? Cela n'a pas fonctionné pour moi jusqu'à ce que j'ai ajouté le modificateur DroiteToleft .


@Alan Moore: Je l'ai testé à Regexbuddy; Je ne pense pas que cela a suggéré l'utilisation de ce modificateur - merci pour l'information!


Réponse brillante - j'ai fini avec un similaire (? U) (. *,) (? = (. *, |, |) seul pour une chaîne séparée de virgule (mon dernier caractère de chaîne est aussi une virgule), donc votre réponse confirme que j'ai trouvé la bonne solution. Vous n'avez pas trouvé votre réponse plus tôt pour éviter de déterminer les choses de moi-même, mais je ne le regrette pas, car la solution difficile est la seule façon d'apprendre des choses comme celle-ci;)



0
votes

Voici une version AWK, pas besoin de regex. xxx

diviser les champs sur ":", passez dans les champs écartés, stockez les éléments dans une matrice. Vérifiez l'existence et s'il existe, sautez. Sinon les imprimer. Vous pouvez traduire cela facilement en code Perl.


0 commentaires