Vérifiez si une chaîne contient une sous-chaîne

113

Comment puis-je vérifier si une chaîne donnée contient une certaine sous-chaîne, en utilisant Perl?

Plus spécifiquement, je veux voir si s1.domain.comest présent dans la variable de chaîne donnée.

Poisson Belgin
la source

Réponses:

231

Pour savoir si une chaîne contient une sous-chaîne, vous pouvez utiliser la indexfonction:

if (index($str, $substr) != -1) {
    print "$str contains $substr\n";
} 

Il renverra la position de la première occurrence de $substrin $str, ou -1 si la sous-chaîne n'est pas trouvée.

Eugène Yarmash
la source
6
Cette méthode est particulièrement préférable lorsque vous effectuez une recherche à l'aide d'une variable - de cette façon, vous n'aurez pas à échapper deux fois les caractères (dans cette chaîne de variables), qui sont spéciaux pour les expressions régulières (comme :).
evgeny9
57

Une autre possibilité est d'utiliser des expressions régulières, ce qui fait la renommée de Perl:

if ($mystring =~ /s1\.domain\.com/) {
   print qq("$mystring" contains "s1.domain.com"\n);
}

Les barres obliques inverses sont nécessaires car a .peut correspondre à n'importe quel caractère. Vous pouvez contourner ce problème en utilisant les opérateurs \Qet \E.

my $substring = "s1.domain.com";
    if ($mystring =~ /\Q$substring\E/) {
   print qq("$mystring" contains "$substring"\n);
}

Ou, vous pouvez faire comme eugene y indiqué et utiliser la fonction d' index . Juste un mot d'avertissement: Index renvoie un -1lorsqu'il ne trouve pas de correspondance au lieu d'un undefou 0.

C'est donc une erreur:

my $substring = "s1.domain.com";
if (not index($mystring, $substr)) {
    print qq("$mystring" doesn't contains "$substring"\n";
} 

Ce sera faux si s1.domain.comc'est au début de votre chaîne. J'ai personnellement été brûlé à ce sujet plus d'une fois.

David W.
la source
Je suppose que index()c'est plus rapide que les regexps dans le cas simple?
G. Cito
1
Une tentative de réponse perl à une question sur la suppression des sous - chaînes - Je ne comparait pas la vitesse , mais =~, index(), ~~et match::simpletout semblait un peu awk-ward ...: - \
G. Cito
Vous devez également vous assurer que les chaînes que vous comparez ne sont pas sensibles à la casse. S1.DOMAIN.COM ne fonctionnera pas pour la sous-chaîne. Mais si vous lc ($ givendomain), puis comparez cela avec "s1.domain.com", alors cela fonctionnera. De plus, la sous-chaîne n'est pas nécessairement la bonne approche - voir ma note ci-dessus à la réponse d'
eugene y
@David W. D'une manière ou d'une autre, je n'arrive pas à faire domain.comcorrespondre subdomain.domain.comavec le REGEX ci-dessus, des idées?
avrono
14

Exemple de sous-chaîne insensible à la casse

Ceci est une extension de la réponse d'Eugene, qui convertit les chaînes en minuscules avant de vérifier la sous-chaîne:

if (index(lc($str), lc($substr)) != -1) {
    print "$str contains $substr\n";
} 
James Oravec
la source
1
Notez que cela fcest recommandé lcpour les comparaisons insensibles à la casse.
melpomene