2008-10-07 30 views
23

Tôi đang tìm một regex sẽ tìm thấy các chữ cái lặp lại. Vì vậy, bất kỳ thư nào hai lần trở lên, ví dụ:Làm thế nào tôi có thể tìm các chữ cái lặp lại với một regex Perl?

booooooot or abbott 

Tôi sẽ không biết chữ cái tôi đang tìm kiếm trước.

Đây là câu hỏi tôi được hỏi trong các cuộc phỏng vấn và sau đó được hỏi trong các cuộc phỏng vấn. Không quá nhiều người hiểu đúng.

Trả lời

52

Bạn có thể tìm thấy bất kỳ bức thư, sau đó sử dụng \1 để tìm cùng một chữ cái lần thứ hai (hoặc nhiều hơn). Nếu bạn chỉ cần biết chữ cái, thì $1 sẽ chứa nó. Nếu không, bạn có thể ghép nối trận đấu thứ hai vào trận đấu đầu tiên.

my $str = "Foooooobar"; 

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

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

Đối với các chữ cái chỉ hoán đổi \ w cho [a-zA-Z]. – TomC

+4

@TomC: Đó không phải là unicode an toàn! –

+0

Bây giờ tôi có thể thay thế các chữ cái gấp đôi chỉ một: Regex.Replace (str, @ "(\ w) \ 1+", "$ 1"); cảm ơn Adam. –

6

Sử dụng \ N để cập đến các nhóm theo thời gian:

/(\w)\1+/g 
0

Làm thế nào về:

(\w)\1+ 

Phần đầu tiên làm cho một nhóm giấu tên xung quanh một nhân vật, sau đó back-tài liệu tham khảo sẽ cho rằng cùng tính cách.

+0

này chỉ khớp với hai ký tự lặp lại đầu tiên, không phải toàn bộ chuỗi con lặp lại. –

9

Tôi nghĩ sử dụng một backreference sẽ làm việc:

(\w)\1+ 

\w về cơ bản là [a-zA-Z_0-9] vì vậy nếu bạn chỉ muốn để phù hợp với chữ giữa A và Z (trường hợp insensitively), sử dụng [a-zA-Z] để thay thế.

(EDIT: hoặc, như Tanktalus nêu trong bình luận của ông (và như những người khác đã trả lời cũng),[[:alpha:]], đó là miền địa phương nhạy cảm)

+0

thay vì [a-zA-Z], chỉ cần sử dụng [[: alpha:]] nhạy cảm với miền địa phương ;-) – Tanktalus

14

Tôi nghĩ bạn thực sự muốn điều này thay vì "\ w" vì bao gồm số và dấu gạch dưới.

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

Ok, ok, tôi có thể gợi ý Leon. Sử dụng điều này cho thế giới unicode hoặc cho công cụ posix.

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

Chúng ta sống trong một thế giới unicode. [a-zA-Z] sẽ không bao gồm hầu hết các ngôn ngữ. [[: alpha:]] sẽ chính xác hơn. –

+0

oh bạn điên người nước ngoài! ; o) vâng, unicode sẽ là cú pháp tốt hơn cho các ký tự tiếng Anh không phải người Mỹ. – Keng

4

Bạn có thể muốn quan tâm đến những gì được coi là thư và điều này tùy thuộc vào ngôn ngữ của bạn. Sử dụng ISO Latin-1 sẽ cho phép các ký tự tiếng Tây phương có dấu được đối sánh dưới dạng chữ cái. Trong chương trình sau, ngôn ngữ mặc định không nhận ra é và do đó créé không khớp. Bỏ ghi chú mã thiết lập miền địa phương, và sau đó nó bắt đầu khớp.

Cũng lưu ý rằng \ w bao gồm các chữ số và ký tự gạch dưới cùng với tất cả các chữ cái. Để chỉ nhận được các chữ cái, bạn cần phải bổ sung các ký tự không phải chữ số, chữ số và dấu gạch dưới. Điều này chỉ để lại chữ cái.

Điều đó có thể dễ hiểu hơn bằng cách đặt khung câu hỏi là câu hỏi "Cụm từ thông dụng nào khớp với bất kỳ chữ số nào trừ 3?" Và câu trả lời là/[^ \ 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

Mã sau sẽ trả về tất cả các ký tự, lặp lại hai lần trở lên.

my $ str = "SSSannnkaaarsss";

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

1

FYI, ngoài RegExBuddy, trang web miễn phí thực sự tiện dụng để kiểm tra cụm từ thông dụng là RegExr at gskinner.com. Xử lý ([[:alpha:]])(\1+) độc đáo.

2

Chỉ cần cho đá, một cách tiếp cận hoàn toàn khác nhau:

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

Có, nó cũng sẽ không tìm thấy chữ cái. Nhưng bạn có thể tìm thấy lỗi tinh tế không? – ysth

0

Tôi nghĩ rằng đây cũng nên làm việc:

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

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

'u' kết hợp sửa đổi với unicode

Các vấn đề liên quan