2008-10-07 6 views
23

Je cherche une regex qui trouvera des lettres répétées. Donc toute lettre deux fois ou plus, par exemple:Comment trouver des lettres répétées avec une regex Perl?

booooooot or abbott 

Je ne connaîtrai pas la lettre que je cherche à l'avance.

C'est une question qui m'a été posée lors d'entrevues et que j'ai posée lors d'entrevues. Pas tellement de gens le font correctement.

Répondre

52

Vous pouvez trouver toute lettre, utilisez \1 pour trouver cette même lettre une seconde fois (ou plus). Si vous avez seulement besoin de connaître la lettre, alors $1 contiendra cette lettre. Sinon, vous pouvez concaténer le deuxième match sur le premier.

my $str = "Foooooobar"; 

$str =~ /(\w)(\1+)/; 

print $1; 
# prints 'o' 
print $1 . $2; 
# prints 'oooooo' 
+0

Pour seulement lettres permuter \ w pour [a-zA-Z]. – TomC

+4

@TomC: Ce n'est pas UNICODE sûr! –

+0

Maintenant, je peux remplacer les lettres doublées pour un seul: Regex.Replace (str, @ "(\ w) \ 1+", "$ 1"); merci Adam. –

6

Utilisez \ N pour désigner des groupes précédents:

/(\w)\1+/g 
0

Que diriez-vous:

(\w)\1+ 

La première partie fait un groupe sans nom autour d'un personnage, puis le dos référence cherche même personnage.

+0

Cette correspond uniquement aux deux premiers caractères récurrents, et non à la totalité de la sous-chaîne qui se répète. –

9

Je pense que l'aide d'un backreference travaillerait:

(\w)\1+ 

\w est essentiellement [a-zA-Z_0-9] donc si vous voulez seulement faire correspondre les lettres entre A et Z (insensible à la casse), utilisez [a-zA-Z] à la place.

(EDIT: ou, comme Tanktalus mentionné dans son commentaire (et que les autres ont répondu aussi bien),[[:alpha:]], qui est locale sensible)

+0

au lieu de [a-zA-Z], il suffit d'utiliser [[: alpha:]] qui est sensible à la locale ;-) – Tanktalus

14

Je pense que vous voulez réellement ceci plutôt que le "\ w" car cela inclut les nombres et le trait de soulignement.

([a-zA-Z])\1+ 

Ok, ok, je peux prendre Leon. Utilisez ceci pour le monde unicode ou pour les choses posix.

([[:alpha:]])\1+ 
+2

Nous vivons dans un monde unicode. [a-zA-Z] ne couvrira pas la plupart des langues. [[: alpha:]] serait plus correct. –

+0

oh vous les étrangers fous! ; o) Oui, unicode serait une meilleure syntaxe pour les caractères anglais non américains. – Keng

4

Vous pouvez faire attention à ce qui est considéré comme une lettre, et cela dépend de votre environnement local. L'utilisation de ISO Latin-1 permet de faire correspondre les caractères en caractères occidentaux accentués sous forme de lettres. Dans le programme suivant, les paramètres régionaux par défaut ne reconnaissent pas é et créé ne correspond pas. Décommentez le code de paramètres régionaux, puis il commence à correspondre.

Notez également que \ w inclut des chiffres et le caractère de soulignement avec toutes les lettres. Pour obtenir seulement les lettres, vous devez prendre le complément des caractères non-alphanum, chiffres et traits de soulignement. Cela ne laisse que des lettres. Cela pourrait être plus facile à comprendre en l'encadrant comme la question «Quelle expression régulière correspond à n'importe quel chiffre sauf 3?», Et la réponse est/[^ \ D3] /.

#! /usr/local/bin/perl 

use strict; 
use warnings; 

# uncomment the following three lines: 
# use locale; 
# use POSIX; 
# setlocale(LC_CTYPE, 'fr_FR.ISO8859-1'); 

while (<DATA>) { 
    chomp; 
    if (/([^\W_0-9])\1+/) { 
     print "$_: dup [$1]\n"; 
    } 
    else { 
     print "$_: nope\n"; 
    } 
} 

__DATA__ 
100 
food 
créé 
a::b 
3

Le code suivant renvoie tous les caractères, qui se répètent deux fois ou plus.

ma $ str = "SSSannnkaaarsss";

print $ str = ~/(\ w) \ 1 +/g;

1

Pour votre information, à part RegexBuddy, un vrai site gratuit pratique pour tester des expressions régulières est RegExr at gskinner.com. Poignées ([[:alpha:]])(\1+) bien.

2

Juste pour voir, une approche complètement différente:

if (($str^substr($str,1)) =~ /\0+/) { 
    print "found ", substr($str, $-[0], $+[0]-$-[0]+1), " at offset ", $-[0]; 
} 
+0

Oui, il trouvera aussi des non-lettres. Mais pouvez-vous trouver le bug subtile? – ysth

0

Je pense que cela devrait aussi fonctionner:

((\w)(?=\2))+\2

0
/(.)\\1{2,}+/u 

'u' correspondant modificateur avec unicode

Questions connexes