2009-03-25 37 views
6

Tôi có một mảng đầy đủ các mẫu mà tôi cần khớp. Bất kỳ cách nào để làm điều đó, khác với một vòng lặp for()? Tôi đang cố gắng làm điều đó theo cách ít tốn kém nhất của CPU, vì tôi sẽ thực hiện hàng chục phút này mỗi phút.Làm thế nào để bạn thực hiện một preg_match nơi mẫu là một mảng, trong php?

Ví dụ thế giới thực là, Im xây dựng trình kiểm tra trạng thái liên kết, sẽ kiểm tra liên kết đến các trang web video trực tuyến khác nhau để đảm bảo rằng video vẫn còn hoạt động. Mỗi tên miền có một số "từ khóa chết", nếu chúng được tìm thấy trong html của một trang, điều đó có nghĩa là tệp đã bị xóa. Chúng được lưu trữ trong mảng. Tôi cần phải phù hợp với nội dung pf mảng, chống lại đầu ra html của trang.

Trả lời

20

Trước hết, nếu bạn có nghĩa là chỉ làm hàng chục mỗi phút, sau đó tôi sẽ không lo lắng khủng khiếp về hiệu suất trong trường hợp này. Những trận đấu này là khá nhanh, và tôi không nghĩ rằng bạn sẽ có một vấn đề hiệu suất bằng cách lặp qua mảng mô hình của bạn và gọi preg_match riêng như thế này:

$matches = false; 
foreach ($pattern_array as $pattern) 
{ 
    if (preg_match($pattern, $page)) 
    { 
    $matches = true; 
    } 
} 

Bạn thực sự có thể kết hợp tất cả các mô hình thành một sử dụng toán tử or giống như một số người đang đề xuất, nhưng đừng chỉ tát chúng cùng với một số |. Điều này sẽ phá vỡ nặng nếu bất kỳ mẫu nào của bạn chứa hoặc toán tử.

Tôi muốn giới thiệu ít nhất nhóm mẫu bằng cách sử dụng dấu ngoặc đơn như:

foreach ($patterns as $pattern) 
{ 
    $grouped_patterns[] = "(" . $pattern . ")"; 
} 
$master_pattern = implode($grouped_patterns, "|"); 

Nhưng ... Tôi không thực sự chắc chắn nếu điều này kết thúc lên được nhanh hơn. Một cái gì đó phải lặp qua chúng, cho dù đó là preg_match hoặc PHP. Nếu tôi phải đoán tôi đoán rằng các trận đấu cá nhân sẽ gần như nhanh và dễ đọc và duy trì hơn.

Cuối cùng, nếu hiệu suất là những gì bạn đang tìm kiếm ở đây, tôi nghĩ điều quan trọng nhất cần làm là kéo các đối sánh không phải regex vào một kiểm tra "chuỗi chứa" đơn giản. Tôi sẽ tưởng tượng rằng một số kiểm tra của bạn phải được kiểm tra chuỗi đơn giản như tìm cách để xem nếu "Trang web này được đóng" là trên trang.

Vì vậy, làm điều này:

foreach ($strings_to_match as $string_to_match) 
{ 
    if (strpos($page, $string_to_match) !== false)) 
    { 
    // etc. 
    break; 
    } 
} 
foreach ($pattern_array as $pattern) 
{ 
    if (preg_match($pattern, $page)) 
    { 
    // etc. 
    break; 
    } 
} 

và tránh càng nhiều càng tốt preg_match() có lẽ sẽ được tăng tốt nhất của bạn. strpos() nhanh hơn preg_match().

+4

Vì lợi ích của nhân viên Google, hãy cân nhắc sử dụng ngắt (http://www.php.net/manual/en/control-structures.break.php) để thoát khỏi vòng lặp foreach khi bạn đã tìm thấy kết quả phù hợp! –

+2

Tôi tin rằng điều này nên là: foreach ($ pattern_array là $ pattern), ít nhất là trong phiên bản PHP của tôi – hellomynameisjoel

+1

Được rồi các bạn ... đã chỉnh sửa để giải quyết các nhận xét của bạn. – danieltalsky

0

Nếu bạn có một loạt các mẫu, những gì bạn có thể làm là nối chúng trong một biểu thức chính quy duy nhất và khớp với điều đó. Không cần lặp lại.

1

Nếu bạn chỉ đang tìm kiếm sự hiện diện của một chuỗi trong một chuỗi khác, hãy dùng strpos vì nó nhanh hơn.

Nếu không, bạn chỉ có thể lặp qua mảng mẫu, gọi preg_match mỗi lần.

10
// assuming you have something like this 
$patterns = array('a','b','\w'); 

// converts the array into a regex friendly or list 
$patterns_flattened = implode('|', $patterns); 

if (preg_match('/'. $patterns_flattened .'/', $string, $matches)) 
{ 
} 

// PS: that's off the top of my head, I didn't check it in a code editor 
+1

Tác vụ này có hoạt động không có dấu ngoặc đơn/dấu ngoặc đơn xung quanh "mẫu" không? – JedatKinports

0

Điều gì về việc thực hiện str_replace() trên HTML bạn nhận được bằng cách sử dụng mảng của mình và sau đó kiểm tra xem HTML ban đầu có bằng với mã gốc không?Điều này sẽ rất nhanh:

$sites = array(
     'you_tube' => array('dead', 'moved'), 
     ... 
); 
foreach ($sites as $site => $deadArray) { 
    // get $html 
    if ($html == str_replace($deadArray, '', $html)) { 
     // video is live 
    } 
} 
+0

str_replace không hoạt động nếu bạn muốn khớp chính xác –

2

Nếu mô hình của bạn không chứa nhiều khoảng trắng, tùy chọn khác sẽ được tránh né các mảng và sử dụng modifier /x. Bây giờ danh sách các biểu thức thông thường sẽ trông như thế này:

$regex = "/ 
pattern1| # search for occurences of 'pattern1' 
pa..ern2| # wildcard search for occurences of 'pa..ern2' 
pat[ ]tern| # search for 'pat tern', whitespace is escaped 
mypat  # Note that the last pattern does NOT have a pipe char 
/x"; 

Với sự sửa đổi /x, khoảng trắng là hoàn toàn bỏ qua, trừ khi trong một lớp nhân vật hoặc trước bởi một dấu gạch chéo. Các nhận xét như trên cũng được cho phép.

Điều này sẽ tránh việc lặp qua mảng.

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