时间戳转换为正则表达式的短代码

时间:2016-11-18 09:29:41

标签: php regex

我正在使用此代码来检测内容的时间戳。

$pattern = '/(?<!:)\d{1,2}:\d{2}(?::\d{2})?(?!(?::\d{2})?\s*[ap]\.?m\.?)(?!.*?["\'])/';
$replacement = '[spp-timestamp time="$0"]';
$foundTimestamp = preg_replace ($pattern,$replacement, $content);

检测短代码的时间戳[spp-timestamp time =“00:00”]

只是想在此添加更多逻辑,以便不从所选div中选择时间戳,例如

<div class="sm2-inline-duration timestamp">0:00</div> and 
<div class="sm2-inline-time timestamp">0:00</div>

例如,如果我将类“timestamp”放在任何div中,则不应使用正则表达式选择它。

有可能吗?

现在它正在检测邮票

00:00,00:00:00,0:00,0:00:00,不选择Am或PM

1 个答案:

答案 0 :(得分:1)

您需要使用DOMDocument解析带有XPath的HTML,这样您就可以使用更简单的正则表达式进行替换。 //div[not(contains(@class, "timestamp"))] xpath表达式将阻止修改div属性中包含timestamp子字符串的class元素的内容。

$html = <<<DATA
<body>
<div class="sm2-inline-duration timestamp">0:00</div>
<div class="sm2-inline-time timestamp">0:00</div>
<div class="sm2-inline-duration">0:00</div>
<div class="sm2-inline-duration">Do not touch this</div>
</body>
DATA;

$dom = new DOMDocument('1.0', 'UTF-8');
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

$pattern = '/(?<!:)\d{1,2}:\d{2}(?::\d{2})?(?!(?::\d{2})?\s*[ap]\.?m\.?)/i';
$replacement = '[spp-timestamp time="$0"]';

$xpath = new DOMXPath($dom);
$divs = $xpath->query('//div[not(contains(@class, "timestamp"))]');

foreach($divs as $div) { 
   $div->nodeValue = preg_replace ($pattern,$replacement, $div->nodeValue);
}

echo $dom->saveHTML();

请参阅PHP demo

出于教育目的,这是一种基于正则表达式的方法,因为这对于使用任意HTML 安全生产无效。

我们的想法是使用可选的捕获组替换无限宽度的不受支持的负向lookbehind,如果组匹配则检查preg_replace_callback内部,并使用相应的替换(如果匹配,我们需要保留原始匹配文本,否则,替换我们的自定义替换)。

$pattern = '/(<div\s+[^<]*?\bclass="[^<"]*\btimestamp\b[^<]*?>[^<]*)?(?<!:)\d{1,2}:\d{2}(?::\d{2})?(?!(?::\d{2})?\s*[ap]\.?m\.?)(?!.*?["\'])/';
$replacement = '[spp-timestamp time="$0"]';
$foundTimestamp = preg_replace_callback($pattern,function($m) {
    return empty($m[1]) ? '[spp-timestamp time="'. $m[0] . '"]' : $m[0];
}, $content);
echo $foundTimestamp;

请参阅another PHP demo