2010-03-24 19 views

Trả lời

10

này hoạt động:

$str =~ s/\b((\w+)\s+\2)\b/[\1]/g; 
+7

'$ str = ~ s/\ b (? (\ W +) (: \ s + \ 2) +) \ b/[\ 1]/g;' để khớp với bất kỳ số lần lặp lại nào –

+6

@briandfoy: ... đó chính xác là câu hỏi được yêu cầu, trước khi bạn thay đổi nó. Và Eric đăng trong một bình luận một phiên bản phù hợp với nhiều hơn một lần lặp lại. – Kip

+0

@brian: Làm thế nào để bạn biết rằng từ 2 dòng ngữ cảnh trong câu hỏi gốc? –

2

Bạn có thể thử:

$str = "Thus joyful Troy Troy maintained the the watch of night..."; 
$str =~s{\b(\w+)\s+\1\b}{[$1 $1]}g; 
print "$str"; # prints Thus joyful [Troy Troy] maintained [the the] watch of night... 

Regex sử dụng: \b(\w+)\s+\1\b

Giải thích:

  • \b: word bondary
  • \w+: một từ
  • (): nhớ từ trên
  • \s+: khoảng trắng
  • \1 : bản ghi nhớ ered từ

Nó có hiệu quả thấy hai đầy đủ từ cách nhau bởi khoảng trắng và đặt [ ] xung quanh họ.

EDIT:

Nếu bạn muốn giữ số lượng khoảng trắng giữa các từ bạn có thể sử dụng:

$str =~s{\b(\w+)(\s+)\1\b}{[$1$2$1]}g; 
+0

điều này không bảo toàn số lượng và loại khoảng trống giữa các từ được sao chép, nếu điều đó quan trọng đối với OP – Kip

+0

@Kip: bạn đã đúng. Cảm ơn. Tôi đã chỉnh sửa ans của tôi. – codaddict

+0

Chỉ tìm thấy hai từ lặp lại. Sẽ tốt hơn nếu nó tìm thấy tất cả các từ lặp đi lặp lại. :) –

12

này tương tự như một trong những Learning Perl bài tập. Bí quyết là để bắt tất cả các từ lặp đi lặp lại, vì vậy bạn cần một "một hoặc nhiều" lượng hóa trên sự trùng lặp:

$str = 'This is Goethe the the the their sentence'; 

$str =~ s/\b((\w+)(?:\s+\2\b)+)/[\1]/g; 

Các tính năng tôi về để sử dụng được mô tả trong hai perlre, khi họ áp dụng tại một mẫu hoặc perlop khi chúng ảnh hưởng đến cách toán tử thay thế thực hiện công việc của nó.

Nếu bạn thích /x cờ để thêm khoảng trắng và bình luận không đáng kể:

$str =~ s/ 
     \b 
     (
     (\w+) 
     (?: 
      \s+ 
      \2 
      \b 
     )+ 
    ) 
    /[\1]/xg; 

Tôi không thích điều đó \2 mặc dù bởi vì tôi ghét đếm vị trí tương đối. Tôi có thể sử dụng backreferences tương đối trong Perl 5.10.Các \g{-1} đề cập đến nhóm chụp ngay trước:

use 5.010; 
$str =~ s/ 
     \b 
     (
     (\w+) 
     (?: 
      \s+ 
      \g{-1} 
      \b 
     )+ 
    ) 
    /[\1]/xg; 

Đếm không phải là tất cả những gì tuyệt vời trong hai, vì vậy tôi có thể sử dụng các trận đấu được dán nhãn:

use 5.010; 
$str =~ s/ 
     \b 
     (
     (?<word>\w+) 
     (?: 
      \s+ 
      \k<word> 
      \b 
     )+ 
    ) 
    /[\1]/xg; 

tôi có thể gắn nhãn chụp đầu tiên ($1) và truy cập vào giá trị của nó trong %+ sau:

use 5.010; 
$str =~ s/ 
     \b 
     (?<dups> 
     (?<word>\w+) 
     (?: 
      \s+ 
      \k<word> 
      \b 
     )+ 
    ) 
    /[$+{dups}]/xg; 

Tôi không thực sự cần chụp lần đầu tiên mặc dù nó thực sự chỉ là ở đây để chỉ mọi thứ phù hợp. Đáng buồn thay, có vẻ như ${^MATCH} không được đặt sớm để tôi sử dụng nó ở mặt thay thế. Tôi nghĩ đó là một lỗi. Điều này sẽ hoạt động nhưng không hoạt động:

$str =~ s/ 
     \b 
     (?<word>\w+) 
     (?: 
      \s+ 
      \k<word> 
      \b 
     )+ 
    /[${^MATCH}]/pgx; # DOESN'T WORK 

Tôi đang kiểm tra lỗi này nhưng sẽ mất một chút thời gian để biên dịch trên máy nhỏ xíu của tôi.

+2

+1 để tìm lỗi trong perl. –

0

Hãy thử như sau:

$str =~ s/\b(\S+)\b(\s+\1\b)+/[\1]/g; 
Các vấn đề liên quan