正则表达式帮助解析日期


Regex help to parse dates

我正在尝试从字符串中获取重要日期...

<tr> <td>Account Registered :</td> <td>2008-02-02</td></tr>
<tr> <td>Account Updated :</td> <td>2014-02-01</td></tr>
<tr> <td>Account Expires :</td> <td>2015-02-02</td></tr>

我已经尝试了以下...

preg_match('#<tr> <td>Account Expires :</td> <td>[0-9]{4}-[0-9]{2}-[0-9]{2}#', $result, $matches);

它提供以下...

array (size=1)
  0 => string '<tr> <td>Account Expires :</td> <td>2015-02-02' (length=38)

我想在 1 个正则表达式或 3 个不同的正则表达式中获取所有三个日期,请帮助我。

谢谢
您可以使用

()来设置可在preg_match_all()中访问的捕获组(与preg_match()不同,它执行全局匹配(。那么你只需要不指定动词Expires

$result = '
<tr> <td>Account Registered :</td> <td>2008-02-02</td></tr>
<tr> <td>Account Updated :</td> <td>2014-02-01</td></tr>
<tr> <td>Account Expires :</td> <td>2015-02-02</td></tr>
';
if(preg_match_all('#<tr>'s*<td>Account's*([^:]*?)'s*:</td>'s*<td>([0-9]{4}-[0-9]{2}-[0-9]{2})#', $result, $matches, PREG_SET_ORDER)) {
    print_r($matches);
    // Array
    // (
    //     [0] => Array
    //         (
    //             [0] => <tr> <td>Account Registered :</td> <td>2008-02-02
    //             [1] => Registered
    //             [2] => 2008-02-02
    //         )
    // 
    //     [1] => Array
    //         (
    //             [0] => <tr> <td>Account Updated :</td> <td>2014-02-01
    //             [1] => Updated
    //             [2] => 2014-02-01
    //         )
    // 
    //     [2] => Array
    //         (
    //             [0] => <tr> <td>Account Expires :</td> <td>2015-02-02
    //             [1] => Expires
    //             [2] => 2015-02-02
    //         )
    // )
}

但是,不应该依赖正则表达式来解析 HTML,因为 HTML 不是一种常规语言。这个"规则"的一个很好的例外是,如果你的HTML来自你自己的代码,并且你知道你可以将其简化为"正则"表达式进行匹配。

您可以将正则表达式用于像这样简单的事情。

preg_match_all('/'b'd{4}-'d{2}-'d{2}'b/', $html, $matches);
print_r($matches[0]);

但我建议使用诸如 DOM 之类的解析器来提取这些值。

// Load your HTML
$dom = DOMDocument::loadHTML('
     <tr> <td>foo bar</td> <td>123456789</td></tr>
     <tr> <td>Account Registered :</td> <td>2008-02-02</td></tr>
     <tr> <td>Account Updated :</td> <td>2014-02-01</td></tr>
     <tr> <td>Account Expires :</td> <td>2015-02-02</td></tr>
     <tr> <td>something else</td> <td>foo</td></tr>
');
$xp  = new DOMXPath($dom);
$tag = $xp->query('//tr/td[contains(.,"Account")]/following-sibling::*[1]');
foreach($tag as $t) { 
   echo $t->nodeValue . "'n";
}
// 2008-02-02
// 2014-02-01
// 2015-02-02

如果您不确定前缀的要求,即(Account可能会更改(,简单的解决方法是验证。

$xp  = new DOMXPath($dom);
$tag = $xp->query('//tr/td/following-sibling::*[1]');
foreach($tag as $t) { 
   $date = date_parse($t->nodeValue);
   if ($date["error_count"] == 0 && 
       checkdate($date["month"], $date["day"], $date["year"])) {
         echo $t->nodeValue . "'n";
   }
}
// 2008-02-02
// 2014-02-01
// 2015-02-02

用于"解析"HTML的简单正则表达式很好。它可能比使用 DOM 解析器更快、更面向未来。

这个捕获所有"标签内的日期":

preg_match_all('#>('d'd'd'd-'d'd-'d'd)<#', $html, $matches);
$dates = $matches[1];
print_r($dates);

使:

Array
(
    [0] => 2008-02-02
    [1] => 2014-02-01
    [2] => 2015-02-02
)

如果$html中有更多的日期,而您只想要这 3 个日期,请忘记这个答案。

如果要在日期(时间(戳中包含时间,请使用以下模式:

#>('d'd'd'd-'d'd-'d'd 'd'd:'d'd:'d'd)<#