2010-02-08 36 views
31

Làm cách nào để viết biểu thức chính quy để khớp với hai chuỗi đã cho, tại bất kỳ vị trí nào trong chuỗi?Cụm từ thông dụng để tìm hai chuỗi ở bất kỳ đâu trong đầu vào

Ví dụ, nếu tôi đang tìm kiếm catmat, nó phải phù hợp:

The cat slept on the mat in front of the fire. 
At 5:00 pm, I found the cat scratching the wool off the mat. 

Không có vấn đề gì trước những chuỗi.

+0

thế nào về ' "catmat" '- nên regex phù hợp với nó? những từ đó có phải là toàn bộ từ không? Làm thế nào về ''vấn đề scathing' ' – Amarghosh

+1

Không, nó không nên phù hợp với một trong số đó. Chỉ hai từ đó, theo thứ tự đó, trước và sau đó là bất kỳ văn bản nào khác. –

+0

Vui lòng xem chỉnh sửa của tôi nếu bạn đang sử dụng mã của tôi. – eyelidlessness

Trả lời

49
/^.*?\bcat\b.*?\bmat\b.*?$/m 

Sử dụng m modifier (trong đó đảm bảo metacharacters đầu/kết thúc trận đấu trên ngắt dòng chứ không phải tại đầu và cuối chuỗi):

  • ^ trận đấu dòng bắt đầu
  • .*? khớp với mọi thứ trên dòng trước ...
  • \b phù hợp với một ranh giới từ sự xuất hiện đầu tiên của một ranh giới từ (như @codaddict đã thảo luận)
  • sau đó là chuỗi cat và một ranh giới từ khác; lưu ý rằng dấu gạch dưới được coi là ký tự "từ", do đó, _cat_ sẽ không phải là đối sánh *;
  • .*?: bất kỳ ký tự trước ...
  • ranh giới, mat, ranh giới
  • .*?: bất kỳ ký tự còn lại trước khi ...
  • $: cuối dòng.

Điều quan trọng là phải sử dụng \b để đảm bảo những lời quy định không nằm trong từ dài hơn, và điều quan trọng là phải sử dụng ký tự đại diện không tham lam (.*?) so với tham lam (.*) vì sau này sẽ thất bại trên chuỗi như " Có một con mèo ở trên tấm thảm dưới con mèo. " (Nó sẽ phù hợp với sự xuất hiện cuối cùng của "mèo" chứ không phải là người đầu tiên.)

* Nếu bạn muốn để có thể phù hợp với _cat_, bạn có thể sử dụng:

/^.*?(?:\b|_)cat(?:\b|_).*?(?:\b|_)mat(?:\b|_).*?$/m 

mà phù hợp hoặc nhấn hoặc ranh giới từ xung quanh các từ được chỉ định. (?:) cho biết nhóm không chụp, có thể trợ giúp hiệu suất hoặc tránh các cảnh quay bị xung đột.

Chỉnh sửa: Một câu hỏi được nêu ra trong các nhận xét về việc liệu giải pháp có hiệu quả cho các cụm từ thay vì chỉ là các từ hay không. Câu trả lời là hoàn toàn có. Sau đây sẽ phù hợp với "Một dòng trong đó bao gồm cả hai cụm từ đầu tiên và cụm từ thứ hai":

/^.*?(?:\b|_)first phrase here(?:\b|_).*?(?:\b|_)second phrase here(?:\b|_).*?$/m 

Chỉnh sửa 2: Nếu tự không quan trọng, bạn có thể sử dụng:

/^.*?(?:\b|_)(first(?:\b|_).*?(?:\b|_)second|second(?:\b|_).*?(?:\b|_)first)(?:\b|_).*?$/m 

Và nếu hiệu suất là thực sự là một vấn đề ở đây, có thể là một vấn đề (nếu động cơ regex của bạn hỗ trợ nó) có thể (nhưng có lẽ sẽ không) thực hiện tốt hơn so với ở trên, nhưng tôi sẽ để lại cả phiên bản phức tạp và thử nghiệm hiệu suất được cho là một bài tập cho người hỏi/người đọc.

Được chỉnh sửa theo nhận xét của @Alan Moore. Tôi không có cơ hội để kiểm tra nó, nhưng tôi sẽ nói lời của bạn cho nó.

+3

'[\ b]' khớp với ** khoảng trắng **, không phải là một ranh giới từ; '\ b' có ý nghĩa khác bên trong một lớp ký tự. –

+0

Người đầu tiên phục vụ mục đích của tôi vừa phải. Cảm ơn. –

+0

@Alan Moore, cảm ơn mẹo. Cách mọi thứ thay đổi ý nghĩa trong một lớp nhân vật luôn ném cho tôi một vòng lặp. – eyelidlessness

2

Bạn có thể thử:

\bcat\b.*\bmat\b 

\b là một neo và phù hợp với một ranh giới từ. Nó sẽ tìm kiếm từ mèo và mat ở bất kỳ nơi nào trong chuỗi có đuôi mèo. Nó sẽ không khớp:

Therez caterpillar on the mat.

nhưng sẽ phù hợp

The cat slept on the mat in front of the fire

Nếu bạn muốn kết hợp các chuỗi có chữ mèo tiếp theo mat, bạn có thể thử:

cat.*mat 

này sẽ phù hợp cả hai ví dụ trên dây.

+0

Hmm .. không hoàn toàn. Nó không phù hợp với một trong hai chuỗi hoàn hảo. Nó khớp với mẫu "mèo ... mat", nhưng không khớp với phần trước và sau đó. –

+0

Oh ok..if anh ấy muốn tìm kiếm cat và mat dưới dạng * words *, bạn có thể thêm đường biên từ. Cảm ơn Phanindra K. – codaddict

+0

Cảm ơn codaddict. Tôi đã sửa đổi regex thành một cái gì đó như thế này:. *? Cat. *? Mat. *? Tôi hy vọng rằng sẽ không có bất kỳ tác dụng phụ không mong muốn. :) –

14
(.* word1.* word2.*)|(.* word2.* word1.*) 
+0

-1: đối sánh sai "nệm thảm khốc", không thành công trên "con mèo trên thảm" và không quan sát thứ tự từ (mặc dù chỉ được chỉ định trong các nhận xét). –

+0

thêm ranh giới từ để không có kết quả chuỗi con – rxgx

+5

Điều này có thể không khớp với những gì OP muốn nhưng nó giúp tôi tìm hai chuỗi trong URL để +1 –

1

bạn không phải sử dụng regex. Trong ngôn ngữ yêu thích của bạn, hãy chia nhỏ khoảng trắng, chuyển qua các từ được chia nhỏ, kiểm tra mèo và chiếu. ví dụ như bằng Python

>>> for line in open("file"): 
...  g=0;f=0 
...  s = line.split() 
...  for item in s: 
...   if item =="cat": f=1 
...   if item =="mat": g=1 
...  if (g,f)==(1,1): print "found: " ,line.rstrip() 

found: The cat slept on the mat in front of the fire. 
found: At 5:00 pm, I found the cat scratching the wool off the mat. 
+0

cũng phù hợp với chiếu trước mèo, đó là câu hỏi đặt ra, nhưng có thể không được ý định :) – Jimmy

+0

cũng, dấu chấm câu. – Jimmy

+0

Vấn đề mà regex giải quyết trong trường hợp này là có sự linh hoạt hơn rất nhiều so với những gì để xem xét một ranh giới. Chỉ xem xét các khoảng trống là ranh giới, điều này sẽ thất bại (mặc dù có vẻ như ý định của người hỏi để phù hợp): 'Hãy coi chừng con mèo; nó nằm trên mat.' Và trong khi regex có thể chậm hơn so với mã tương đương để làm điều này một cách an toàn hơn, mã tương đương có thể yêu cầu hàng chục dòng mã để làm điều đó đúng. Có một cảnh báo hợp lý về SO về regex, nhưng nó thực sự là công cụ thích hợp cho công việc này. – eyelidlessness

0

này hoạt động để tìm các file có chứa cả hai string1 và string2

(((|. \ N) ) Chuỗi1 ((|. \ N)) String2) | (((|. \ N) ) String2 ((|. \ n)) Chuỗi1)

trận đấu bất kỳ số lượng ký tự hoặc các lĩnh vực dòng tiếp theo Chuỗi1 tiếp theo bất kỳ số lượng ký tự hoặc dòng Fields tiếp theo String2 hOẶC trận đấu bất kỳ số của các ký tự hoặc trường dòng cho llowed bởi String2 tiếp theo bất kỳ số lượng ký tự hoặc các lĩnh vực dòng tiếp theo Chuỗi1

+0

Xin chào, cho cùng một ví dụ và mèo đầu tiên. bạn có thể tư vấn cách thực hiện tìm regex âm hay không. ví dụ. nếu tôi tìm thấy mèo và thảm trong một dòng. Tôi nên bỏ qua dòng đó. nhưng nếu tìm thấy con mèo với bất cứ điều gì khác tôi nên nắm bắt điều đó. Vì vậy, dưới đây gửi dòng mèo với thảm nên được xem xét. 'Con mèo ngủ trên tấm thảm trước ngọn lửa.' 'Vào lúc 5:00 chiều, tôi thấy con mèo gãi len ra khỏi thảm' – enthuguy

2

này là khá dễ dàng trên điện yêu cầu chế biến:

(string1(.|\n)*string2)|(string2(.|\n)*string1)

tôi đã sử dụng này trong visual studio 2013 để tìm tất cả các file có cả chuỗi 1 và 2 trong đó.

+0

Tuyệt vời! Nhưng làm thế nào tôi có thể tránh khoảng trắng và các ký tự không phải từ khác ở giữa. Tôi đang cố gắng tìm tất cả sự kết hợp của toàn bộ các từ với các từ 'học sinh' và 'tên'. Vì vậy, "studentpreferredname" và "student_name" là ok, nhưng không phải "StudentID = @ StudentID ORDER BY q.QualificationName" – Fandango68

3

Nếu bạn hoàn toàn cần phải chỉ sử dụng một regex sau đó

/(?=.*?(string1))(?=.*?(string2))/is 

i modifier = case-insensitive

. *?đánh giá lười biếng đối với bất kỳ ký tự (phù hợp càng ít càng tốt)

? = cho Positive lookahead nó phải phù hợp với nơi modifier

s =. (thời gian) cũng chấp nhận ngắt dòng

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