Je voudrais extraire des modèles selon a [a-z]
à partir d'une longue chaîne et afficher uniquement des valeurs distinctes. Par exemple pour la chaîne suivante dans $x
perl -e "$x = 'abx1acy2acz3ab'";
Les résultats devraient être:
ab
ac
Problème: Il n'y a pas de règle pour diviser l'enregistrement / la chaîne en un tableau qui facilite l'extraction du motif.
3 Réponses :
Vous obtiendrez des modèles distincts par cette expression régulière (si vous ne vous souciez pas de leur ordre):
(a[a-z])(?!.*\1)
(a [a-z])
- correspond à la lettre a
suivie de toute autre lettre de la plage a-z
. Le contenu est capturé dans le groupe 1 (?!. * \ 1)
- recherche négative pour s'assurer que le contenu du groupe 1 n'est pas présent plus tard dans la chaîne.
Merci pour cette expression rationnelle et pour l'expansion. Comment puis-je imprimer chaque motif distinct? perl -e "$ x = 'abx1acy2acz3ab'; $ x = ~ /(a[az )(?!.*\1)/g; print $ 1;"
imprime uniquement ac
.
C'est une solution assez intelligente!
@giordano .. vous faites une recherche globale, donc enroulez-la dans une boucle while perl -e '$ x = "abx1acy2acz3ab"; while ($ x = ~ /(a[a-z[) )(?!.*\1)/g) {print "$ 1 \ n"} '
Si vous souhaitez des données uniques, envisagez d'utiliser un hachage.
#!/usr/bin/perl use strict; use warnings; use feature 'say'; $_ = 'abx1acy2acz3ab'; my %seen; for (/(a[a-z])/g) { say $_ unless $seen{$_}++; }
Ceci est très intéressant: il est possible de filtrer une chaîne en utilisant pour
. Je ne savais pas ça. Très utile.
@giordano: Vous n'êtes pas vraiment en train d'itérer sur la chaîne. /(...)/g
renverra une liste de correspondances et vous parcourez cette liste.
Un autre one-liner Perl
$ perl -le ' $x="abxaxy2acz3ab" ; %kv=$x=~/(a[a-z])((?<=.))/g; $,="\n"; print keys %kv ' ax ab ac $
avec une autre entrée:
$ perl -le ' $x="abx1acy2acz3ab" ;%kv=$x=~/(a[a-z])((?<=.))/g; $,="\n"; print keys %kv ' ac ab $
Cela ne fonctionne pas si la chaîne d'entrée est, par exemple, "abx1axy2acz3ab".
@Dave .. Je viens de réparer .. pourriez-vous s'il vous plaît revoir
Merci Dave, mais quelque chose me surprend .. Je m'attends à ce que le caractère correspondant à [a-z] entre dans les "valeurs" du hachage .. mais il est imprimé vide .. Une idée pourquoi c'est une chaîne vide?
m // g renvoie une liste. Vous obtenez 8 correspondances, dont une sur seconde est vide ( ((? <=.))
), et celles-ci deviennent vos valeurs de hachage.
C'est une façon intéressante d'utiliser le hachage pour l'unicité de toutes les correspondances. Donc, vous vous souciez des clés ici et donc tout va bien. (Et je n'obtiens pas cette ligne vide à la fin de l'impression?!)
@jhnc .. si je comprends bien, le lookbehind positif ne consomme aucune chaîne et donc si des groupes de capture en sont couverts, alors ceux-ci ne consomment pas non plus ... n'est-ce pas?
Si vous voulez vraiment capturer les valeurs, alors les parenthèses de capture doivent contourner le modèle lui-même (pas l'assertion entière): /(a[az unity )(?<=(.))/g;
, pour perl -E '$ _ = "abxaxyaczab"; % h = /(a[a-z glacée)(?=(.))/g; dites "$ _ => $ h {$ _}" pour les clés% h '
@ stack0114106 Avec perl, j'ai tendance à essayer des choses plutôt que de trop réfléchir! :) perl -le '$ x = "abxaxy2acz3ab"; @g = ($ x = ~ / (a [a-z]) ((? <=.)) / g); imprimer "<< $ _ >>" pour @g '
@ stack0114106 J'ai aimé votre réponse ici, merci pour votre temps
N'y a-t-il pas un DS "défini" en perl? Cela pourrait probablement aider
@Predicate: Nous avons tendance à utiliser des hachages pour modéliser des ensembles.