web-dev-qa-db-fra.com

Quelle expression régulière peut correspondre à des séquences du même caractère?

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.

38
Bill

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+
74
David Hanak

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>+/;
}
10
oylenshpeegul

Cela correspondra plus que\w serait, comme @@@: 

/(.)\1+/
4
gpojd

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!

1
Edmund

C’est à cela que servent les références arrières.

m/(\w)\1\1/

fera l'affaire.

1
friedo

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!");
    }
}

}

0
Nishad

Répondant à ma propre question, mais j'ai compris

m|(\w)\1+|
0
Bill