正则表达式只改变div中的数字

时间:2017-12-08 18:51:20

标签: php regex html-parsing

我现在有这个正则表达式

/<div[^>]*>|(\d{1,9}\.\d{2})/

检测<div>的开头,并以货币格式对其进行分组。

如果我有这样的字符串

<div class="foo">Hello world 4546.00 and 6596.45 bla bla bla</div>

我只想用preg_replace

替换其中的数字

正如您在下面的示例中所看到的,我不希望选择div之外的数字,只选择里面的数字。

https://regex101.com/r/AZd896/1/

2 个答案:

答案 0 :(得分:1)

我不确定你为什么如此迅速地投票,但我只能假设这是因为这个问题的主题及其与regex match open tags except xhtml self contained tags的关系。

这绝不是最佳答案,但是,在您的问题范围内,它确实解决了您的问题。

代码

See regex in use here

(?:<div[^>]*>|\G(?!\A))(?:(?!</div>).)*?\K\d{1,9}\.\d{2}

如果<div>标记可能跨越多行,您可以添加s修饰符,以允许.匹配换行符as seen here

结果

输入

dasdfasdf 355.56 asdfasd
<div class="sdaf">sdfsad 36546545643.00 asdfa sdf sadfasdf 544.45 sadfs</div>
dasdfasdf 355.56 asdfasd

输出

dasdfasdf 355.56 asdfasd
<div class="sdaf">sdfsad 36 asdfa sdf sadfasdf  sadfs</div>
dasdfasdf 355.56 asdfasd

说明

  • (?:<div[^>]*>|\G(?!\A))匹配以下任一项
    • <div[^>]*>符合以下条件
      • <div按字面意思匹配
      • [^>]*匹配集合中不存在的任何数字(除>以外的任何内容)
      • >按字面意思匹配
    • \G(?!\A)在上一场比赛结束时断言位置
  • (?:(?!</div>).)*? Tempered greedy token任意次数匹配任何字符,但尽可能少,并确保不匹配</div>
  • \K重置报告的匹配的起点。任何以前消费的字符都不再包含在最终匹配中。
  • \d{1,9}\.\d{2}匹配1-9位数字,后跟一个文字点.,后跟2位数字

答案 1 :(得分:1)

虽然使用正则表达式解析HTML听起来很有趣,但请使用正确的XML解析器。您可以使用以下DOMDocument代码来实现此功能:

<?php

$html = 'dasdfasdf 355.56 asdfasd
<div class="sdaf">sdfsad 36546545643.00 asdfa sdf sadfasdf 544.45 sadfs</div>';

$doc = new DOMDocument();
$doc->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$divs = $doc->getElementsByTagName('div');
foreach($divs as $div)
{
    $innerText = $div->nodeValue;
    $div->nodeValue = preg_replace('(\d{1,9}\.\d{2})', 'whatever', $innerText);
}

$html = $doc->saveHTML();

var_dump($html);

现在,有了这个,您只需要使用REGEX解析内部字符串而不是<div>本身。