2012-08-02 82 views
1
集團

我從一個很長的HTML表格解析信息;現在我正在使用的代碼使用DOMDocument,DOMElement(etc)類來解析。我想要做的運行鍼對Regex'ing出的信息表的當前方法的性能測試,但我不能得到正確的表達。PHP正則表達式中提取內容物從非捕獲

表的

HTML行看起來是這樣的:

<tr><td> JON SMITH  </td><td> 2000-09-29 </td></tr> 

而且我一直在試圖表達看起來是這樣的:

/(?:<td>([a-zA-Z\s]*?)<\/td><td>([0-9-\s]*?)<\/td>)/ 

上述表達的問題是,它是返回整個行內容而不僅僅是內部列的內容。理想情況下,preg_match_all陣列結果將名稱,日期,姓名,日期等

這是做合理的事情,或者我應該堅持使用DOM技術?如果這是合理的,有人可以藉助正則表達式嗎?

謝謝!

編輯:如果有人在將來遇到這種情況,RegEx解決方案比使用DOM類有更好的性能;在我的情況下,這是秒和分鐘之間的差異。

+0

請從正則表達式解析HTML避免,因爲它會[驅使你į̷̷͚̤̤̖̦͍͗̒̈̅̄n̨͖͓̹͍͎͔͈̝͐ͪ͛̄͛ṣ̷̵̞̦ͤ̅̉̋ͪ͑͛ͥ͜a̷̘͖̮͔͎͛̇̏̒͆̆͘n͇͔̤̼͙̩͖̭ͤ͋̉͌͟eͥ͒͆ͧͨ̽͞҉̹͍̳̻͢(HTTP://計算器.COM /問題/ 1732348 /正則表達式匹配開放標籤,除了-XHTML-自足標籤/ 1732454#1732454)。改爲使用[HTML解析器](http://stackoverflow.com/questions/292926/robust-mature-html-parser-for-php)。 – 2012-08-02 13:39:39

+0

感謝您的提示。如前所述,我目前正在使用PHP DOM類進行解析;在這樣的情況下,如果RegEx提供更好的性能,我願意嘗試。通常我會100%同意你的觀點並堅持正確的HTML解析選項。 – 2012-08-02 13:48:29

回答

0

使用preg_match_all( )並將第三個參數傳遞給數組來填充和第四個參數PREG_SET_ORDER。

preg_match_all("/(?:<td>([a-zA-Z\s]*?)<\/td><td>([0-9-\s]*?)<\/td>)/", $html, $matches, PREG_SET_ORDER); 

結果陣列應該是這樣的:

$matches => array(
    [0] => array(
     [0] => '<td> JON SMITH  </td><td> 2000-09-29 </td>', 
     [1] => ' JON SMITH  ', 
     [2] => ' 2000-09-29 ' 
    ), 
    [1] => array(
     [0] => '<td> JACK BOLD  </td><td> 2000-10-20 </td>', 
     [1] => ' JACK BOLD  ', 
     [2] => ' 2000-10-20 ' 
    ), 
    ... 
); 

請參考preg_match_all() documentation.

+0

這正是我要找的,謝謝! – 2012-08-02 14:08:18

+0

歡迎:) – Oussama 2012-08-02 14:09:01

+0

運行性能測試,它適用於正確的HTML解析技術。 – 2012-08-02 17:42:14

0

我的解決方案:

step1。搜索<table>...</table>
/<table[^>]*+>([^<]*+(?:(?!<\/?+table)<[^<]*+)*+)<\/table>/i

step2。從step1搜索全部<tr>...</tr>組1:
/<tr[^>]*+>([^<]*+(?:(?!<\/?+tr)<[^<]*+)*+)<\/tr>/ix

step3。從每一個<td>...</td>提取數據(來自步驟2組1):
/<td[^>]*+>([^<]*+(?:(?!<\/?+td)<[^<]*+)*+)<\/td>/ix

這些可怕的圖案是指Mastering Regular Expressions 3rd

示例代碼:

<?php 
$foo = '<tr><td> JON SMITH  </td><td> 2000-09-29 </td></tr>'; 
if(preg_match_all('/<td[^>]*+>([^<]*+(?:(?!<\/?+td)<[^<]*+)*+)<\/td>/ix', $foo, $matches) > 0){ 
    for($i = 0; $i < count($matches[0]); ++$i) 
     printf("%s\n", $matches[0][$i]); 

    for($i = 0; $i < count($matches[1]); ++$i) 
     printf("%s\n", $matches[1][$i]); 
} 
?> 

輸出:

<td> JON SMITH  </td> 
<td> 2000-09-29 </td> 
JON SMITH 
2000-09-29 
+0

我跑了一個測試,雖然它確實工作(並且效果很好),但它稍微不太優雅,並且性能比上述答案略差。無論如何感謝:) – 2012-08-02 17:44:51

+0

真的嗎?我用RegexBuddy再次測試了我的示例代碼。在18個步驟中找到匹配。但另一個解決方案需要118個步驟:P。基本上,我的模式結合展開循環技術和佔有量詞,它應該是一個最快的解決方案。 – godspeedlee 2012-08-03 01:55:16