J'ai une chaîne comme
XXXXYYYYZZZYYZZZYYYY
qui doit être converti en
XXXXAAAYZZZAYZZZAAAY
$ s = ~ s / Y {2} + / AY / g;
ceci a 2 problèmes, {2} +
obtiendra YYYY à AYAY; et AY n'est pas la même longueur que YYYY
(en attendant AAAY
)
Comment faire cela en perl?
3 Réponses :
Utilisez un "look-ahead":
$s =~ s/Y(?=Y+)/A/g;
(? = Y +)
signifie "suivi d'un ou plusieurs caractères Y
", donc tout caractère Y
suivi d'un autre caractère Y
sera remplacé par un A
.
Il y a toujours plus d'une façon de le faire. Ma suggestion est de saisir tous les Y sauf le dernier, puis de l'utiliser pour créer une chaîne de As de même longueur. Le modificateur e
dit à perl d'exécuter le code du côté remplacement au lieu de l'utiliser directement, et le modificateur r
dit à = ~
de renvoyer le résultat de la substitution au lieu de modifier directement le texte d'entrée (utile pour ces tests à une ligne, entre autres).
$ perl -E 'say shift =~ s/(Y+)(?=Y)/"A"x length$1/gre' XXXXYYYYZZZYYZZZYYYY XXXXAAAYZZZAYZZZAAAY
Ce n'est pas vraiment la même chose - vous avez déplacé le + en dehors de la capture, donc la longueur est toujours de 1, et votre remplacement omettra le (s) de fin, et cela signifie que plus de texte est mis en correspondance et donc remplacé. Oui, cela peut fonctionner sans anticipation, mais je préférerais que cela fonctionne.
mon mauvais, ouais (Y +) Y
que vous pouvez remplacer par la longueur du groupe capturé comme A
et un Y
supplémentaire
Regexes: ne fonctionnent généralement pas à la première tentative. :) C'est pourquoi j'ai dû essayer trois fois pour que la réponse ci-dessus fonctionne :)
$ s = ~ s / Y {2} + / AY / g
Le modèle RHS est un modèle obscur de manière ambiguë: Y {2} +
, c'est un modèle d'expression régulière très rarement utilisé, sauf si {} +
est très rarement disponible dans quelques moteurs de regex avancés, y compris perl peut-être, comme une fonctionnalité regex appelée «groupement atomique».
Vous avez peut-être voulu dire (Y {2}) + qui est (YY) +
ou Y {2,}
qui est YY +
en perl, ce n'est pas une évidence simple et facile car il prend en charge la fonctionnalité lookaround
echo XXXXYYYYZZZYYZZZYYYY |sed -E 's/YY+/&\n/g;s/Y/A/g;s/A\n/Y/g'
en fait un moteur de regex plus bas, un tel sed peut toujours le faire bien que de manière lourde et difficile p >
perl -e '$s=XXXXYYYYZZZYYZZZYYYY ;$s =~ s/Y(?=Y)/A/g;print $s'