2012-01-06 19 views
7

Trường hợp:biểu thức chính quy - trận đấu từ duy nhất một lần trong dòng

  1. ehello tạm biệt hellot chào tạm biệt
  2. ehello tạm biệt hello hello tạm biệt

Tôi muốn để phù hợp với dòng 1 (chỉ có 'hello 'một lần!) KHÔNG muốn khớp với dòng 2 (chứa' xin chào 'nhiều lần)

Đã thử sử dụng cái nhìn tiêu cực phía trước và những gì không ... mà không có bất kỳ succ thực nào ESS ..

Trả lời

4

Một lựa chọn đơn giản là thế này (bằng cách sử dụng lá cờ multiline và không dot-all):

^(?!.*\bhello\b.*\bhello\b).*\bhello\b.*$ 

Đầu tiên, kiểm tra xem bạn không có 'hello' hai lần, và sau đó kiểm tra xem bạn có ít nhất một lần.
Có nhiều cách khác để kiểm tra điều tương tự, nhưng tôi nghĩ điều này khá đơn giản.

Tất nhiên, bạn có thể trận đấu đơn giản cho \bhello\b và đếm số lượng các trận đấu ...

+0

Tại sao không chỉ tìm thấy nó một lần và kiểm tra xem nó không tồn tại một lần nữa sau đó? Dường như một chút ít lặp đi lặp lại theo cách đó. – Wiseguy

+1

@Wiseguy - Một patten như '^. * Hello (?!. * Hello)' sẽ không hoạt động, bởi vì nó sẽ luôn khớp với 'hello' cuối cùng của dòng. Bạn sẽ cần một cái gì đó như '^ (? :(?! hello).) * Hello (?!. * Hello)', không thanh lịch hơn nhiều. Tôi có thể đã bỏ lỡ một cái gì đó đơn giản mặc dù ... – Kobi

+0

@Wiseguy - no. Động cơ regex cố gắng để phù hợp, không thất bại. Nó có thể phù hợp, vì vậy nó sẽ. – Kobi

1

Vì bạn chỉ lo lắng về những lời (tức là mã thông báo cách nhau bởi khoảng trắng), bạn chỉ có thể chia nhỏ trên không gian và xem tần suất "hello" xuất hiện. Vì bạn đã không đề cập đến một ngôn ngữ, đây là một thực hiện trong Perl:

use strict; 
use warnings; 

my $a1="ehello goodbye hellot hello goodbye"; 
my $a2="ehello goodbye hello hello goodbye"; 

my @arr1=split(/\s+/,$a1); 
my @arr2=split(/\s+/,$a2); 

#grab the number of times that "hello" appears 

my $num_hello1=scalar(grep{$_ eq "hello"}@arr1); 
my $num_hello2=scalar(grep{$_ eq "hello"}@arr2); 

print "$num_hello1, $num_hello2\n"; 

Đầu ra là

1, 2 
2

Một regex chung sẽ là:

^(?:\b(\w+)\b\W*(?!.*?\b\1\b))*\z 

Altho nó có thể là sạch hơn để đảo ngược kết quả của trận đấu này:

\b(\w+)\b(?=.*?\b\1\b) 

Điều này hoạt động bằng cách kết hợp một từ và chụp nó, sau đó đảm bảo với một lookahead và một backreference rằng nó không/không làm theo bất cứ nơi nào trong chuỗi.

+0

Doh, tôi đã hiểu sai câu hỏi, nghĩ 'hello' có thể là bất kỳ từ nào và mục đích của regex là đảm bảo không lặp lại từ nào. Sẽ để lại câu trả lời trong trường hợp đó là bất kỳ quan tâm đến bất cứ ai. – Qtax

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