Je veux faire correspondre Internet.
ou Internet
à la fin de la chaîne.
Je peux écrire:
$str =~ m/Internet\.|Internet$/
Existe-t-il un moyen d'écrire regex
sans répéter Internet
?
3 Réponses :
Vous pouvez utiliser des parenthèses pour regrouper des éléments, et le tube fonctionne localement au sein du groupe.
Cela signifie que vous pouvez transformer ab | ac
en a (b | c)
. Notez que cela crée également automatiquement un groupe de capture 1 ; si vous ne voulez pas cela, vous pouvez utiliser a(?:b|c)
.
Donc, dans votre cas, vous pouvez écrire 2 sup >:
$str =~ /Internet(\.|$)/
(Ou /Internet(?:\.|$)/
pour utiliser un groupe non capturant, mais il semble que ce ne soit pas le cas peu importe ici.)
1: Cela signifie que le contenu du groupe correspondant irait dans $ 1
(ou $ 2
, etc. selon le nombre-ième de groupe), donc avec a (b | c)
vous obtiendrez soit b
ou c
dans $1
.
2: J'ai supprimé le m parce que c'est de toute façon le mode par défaut pour la correspondance de modèles.
Remarque: Comme mentionné par le commentateur JvdV ci-dessous, en fonction de votre cas d'utilisation vous pouvez également envisager d'ajouter une limite de mot avant le mot Internet
. Ensuite, il ne correspondrait qu'à quelque chose comme Internet.
ou (Internet.)
mais pas IIIIInternet.
. Vous feriez cela en utilisant \ b
, par exemple /\bInternet(\.|$)/
Tout d'abord, $
ne correspond pas (juste) à la fin de la chaîne. Vous voulez \ z
pour cela.
(?: ...)
peut être utilisé car les parenthèses sont utilisées en mathématiques. Cela nous permet de factoriser le préfixe commun comme suit:
/ ^ (?&IDENT) (?: \. (?&IDENT) )* \z (?(DEFINE) (?<IDENT> [a-zA-Z][a-zA-Z0-9_]* ) ) /x
En général, nous pouvons utiliser l'interpolation ou DEFINE
. P >
Par exemple, regardons la correspondance suivante qui utilise un long motif répété que nous ne pouvons pas simplement éliminer:
my $ident = qr/[a-zA-Z][a-zA-Z0-9_]*/; / ^ $ident (?: \. $ident )* \z /x
En utilisant l'interpolation:
XXX
Utilisation de DEFINE
(mieux):
/ ^ [a-zA-Z][a-zA-Z0-9_]* (?: \. [a-zA-Z][a-zA-Z0-9_]* )* \z /x
Il y a toujours une répétition, mais au lieu de répéter un modèle complexe, nous répétons un mot simple et les fautes d’orthographe entraîneront une erreur fatale plutôt qu’une mauvaise conduite potentiellement subtile.
Pourquoi utiliser DEFINE
" mieux " - parce qu'il n'y a pas besoin d'une variable supplémentaire alors, ou y a-t-il encore d'autres raisons? (Efficacité?)
@zdim, Parce que l'autre manière compile le modèle, le stringifie, puis le recompile. (Ce n'est que si le motif entier est une var que la stringification et la recompilation sont évitées.) Et bien sûr, il doit vérifier si $ ident
a changé si vous appelez la correspondance dans une boucle.
En fonction de votre entrée, il peut arriver au début / au milieu / à la fin du contenu. Il serait donc préférable d'utiliser le code ci-dessous pour éviter la casse:
$str =~ m/[Ii]nternet(\.|$)/ or $str =~ m/Internet(\.|$)/i
De plus, si vous souhaitez stocker dans le groupe, utilisez des parenthèses.
Leur regex actuelle permet soit
Internet.
ouInternet
, donc/Internet\.?$/
ne fonctionnerait pas car cela ne correspondrait pas par exempleInternet. Et bien plus.
même s'il le faut.