Un ami m'a posé la question et m'a laissé perplexe: existe-t-il un moyen de créer une expression régulière qui correspond à une séquence du même caractère? Par exemple, match sur "aaa", "bbb", mais pas "abc"?
m|\w{2,3}|
Ne ferait pas l'affaire, car elle correspondrait à "abc".
m|a{2,3}|
Ne ferait pas l'affaire, car elle ne correspondrait pas à 'bbb', 'ccc', etc.
Chose sûre! Le groupement et les références sont vos amis:
(.)\1+
Correspondra à 2 occurrences ou plus du même personnage. Pour les caractères constitutifs de Word uniquement, utilisez \w
au lieu de .
, c'est-à-dire:
(\w)\1+
Notez que dans Perl 5.10, nous avons également des notations alternatives pour les références arrières.
foreach (qw(aaa bbb abc)) {
say;
say ' original' if /(\w)\1+/;
say ' new way' if /(\w)\g{1}+/;
say ' relative' if /(\w)\g{-1}+/;
say ' named' if /(?'char'\w)\g{char}+/;
say ' named' if /(?<char>\w)\k<char>+/;
}
Cela correspondra plus que\w serait, comme @@@:
/(.)\1+/
Ceci est également possible en utilisant des expressions régulières pures (c'est-à-dire celles décrivant les langages réguliers - not Perl regexps). Malheureusement, cela signifie une expression rationnelle dont la longueur est proportionnelle à la taille de l'alphabet, par exemple:
(a* + b* + ... + z*)
Où a ... z sont les symboles de l'alphabet fini.
Ainsi, les expressions rationnelles Perl, bien qu’elles soient un sur-ensemble d’expressions régulières pures, ont définitivement leurs avantages, même lorsque vous souhaitez les utiliser uniquement pour des expressions régulières pures!
C’est à cela que servent les références arrières.
m/(\w)\1\1/
fera l'affaire.
Si vous utilisez Java et recherchez les caractères en double dans une chaîne donnée, voici le code,
public class Test {
public static void main(String args[]) {
String s = "abbc";
if (s.matches(".*([a-zA-Z])\\1+.*")) {
System.out.println("Duplicate found!");
} else {
System.out.println("Duplicate not found!");
}
}
}
Répondant à ma propre question, mais j'ai compris
m|(\w)\1+|