2011-11-11 26 views
7

Tôi đến để yêu cầu hỗ trợ của bạn sau rất nhiều nghiên cứu về vấn đề này:cách giới hạn các kết quả phù hợp trên perl bằng regex?

Tôi đang cố gắng hạn chế sự lặp lại của các thay thế mà một regex Perl thực hiện trên một văn bản lớn. Tôi đã tìm kiếm trong Google và thấy rằng định dạng là {2,3} (tối thiểu, tối đa) tuy nhiên điều này có vẻ là một cách khác mà cú pháp tôi đang sử dụng.

$replaced=~s/$var/$var2/g; # replaces all ocurrences 
$replaced=~s/$var/$var2/; # replaces only first one 

giải pháp tối ưu phi của tôi:

for($i=0; $i<8; $i++){ 

    $replaced=~s/$var/$var2/; 
} 

Những gì tôi đã cố gắng:

$replaced=~s/$var/$var2/{8}; 
$replaced=~s/$var/$var2{8}/; 

Bất kỳ trợ giúp sẽ được đánh giá cao!

chỉnh sửa: OK vì vậy, có khá nhiều thứ phải liên quan đến vòng lặp huh .. không phải là lạ khi không có thông số được xây dựng để hạn chế nó ??

+1

tại sao bạn cho rằng giải pháp của mình không tối ưu? – Vlad

+0

Vòng lặp for là nhiều hay ít như thế nào tôi sẽ làm điều đó. –

+2

cũng là những gì nếu im phân tích một tập tin 100mb và ocurrences là trên nửa thứ hai của khối, tôi sẽ đọc 50mb đầu tiên mọi lúc, nếu điều này có thể được giới hạn nó sẽ chỉ là một đọc – isJustMe

Trả lời

7

Những câu trả lời với \G có lẽ là cách thiết thực nhất để làm những gì bạn muốn, nhưng chỉ để cho vui hoặc gây dựng hoặc bất cứ điều gì, đây là một cách khác (yêu cầu perl 5.10 hoặc cao hơn), sử dụng khẳng định mã và backtracking control verbs(*COMMIT)(*FAIL):

my $str = "Bananas in pajamas are coming down the stairs"; 
my $limit = 3; 
my $count; 

$str =~ s/(*COMMIT)(?(?{ $count++ >= 3 })(*FAIL))a/A/g; 
say $str; 

mà rời khỏi văn bản "chuối trong Pyjama đang đi xuống cầu thang" trong $str - chỉ là người đầu tiên ba "a" s đã bị ảnh hưởng và nó dừng lại quét chuỗi hệ phù hợp khác sau khi thứ ba .

+0

Tôi thường đặt bộ đếm ở phần thay thế. – tchrist

+0

@tchrist Tôi không theo dõi. Quan tâm để giải thích? Ngoài ra, trả lời thư của tôi lại: casefolding! ;) – hobbs

+1

's/(a)/$ count ++ <3? "A": $ 1/ge' – tchrist

4

Tôi không thông thạo Perl, nhưng tôi tin rằng bạn muốn sử dụng "\G Assertion" (more info here), mà sẽ tiếp tục tìm kiếm một trận đấu mới tại nơi các trận đấu trước đó rời đi:

for($i=0; $i<8; $i++){ 

    $replaced=~s/\G$var/$var2/; 
} 

tôi không tích cực cho dù đó là trong thực tế hiệu quả hơn, nhưng chắc chắn nó có vẻ như đó là những gì nó dành cho ...

+1

Biến '$ i' không làm gì ở đây. Một cách thanh lịch hơn để viết này là 's/\ G $ var/$ var2/cho 1 .. 8;' – Zaid

+0

@Zaid: nhưng bạn không thể ommit '$ replace = ~' trong trường hợp này, bởi vì 'for 1 .. 8' bộ '$ _'. – choroba

+0

Đúng, bắt đầu bằng '$ replace = ~' – Zaid

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