【问题标题】:My regex is not replacing correctly我的正则表达式没有正确替换
【发布时间】:2015-03-19 19:22:24
【问题描述】:

我有这个正则表达式:/(?:(?<=(?:style=["])).*)(line-height.*?)[;"]/i

$regex = '/(?:(?<=(?:style=["])).*)(line-height.*?)[;"]/i';

preg_replace("/(?:(?<=(?:style=[\"'])).*)(line-height.*?)[;\"]/i", "HELLO", $input);

这是输入:

    <li><span style="line-height: 20.14399986267089px">500.00dkk</span></li>
<li style="color:red; line-height: 21.14399986267089px"></li>

我只想用 HELLO 替换出现的“line-height: SOMENUMBERpx”(它还必须以样式标记开头): 但我不能让它正常工作。现在它替换了 line-height 属性,但它也替换了:color:red,这是我不想要的。

这是我想要的输出:

<li><span style=HELLO>500.00dkk</span></li> 
<li style="color:red; HELLO"></li>

谁能看到我做错了什么?

【问题讨论】:

  • 那些line-height 样式总是在&lt;li&gt; 和&lt;span&gt; 中吗?

标签: php regex html-parsing preg-replace


【解决方案1】:

我会使用DOM 解析器来提取样式属性并使用preg_replace() 修改内容:

$input = <<<EOF
<li><span style="line-height: 20.14399986267089px">500.00dkk</span></li>
<li style="color:red; line-height: 21.14399986267089px"></li>
EOF;

# Create a document from input
$doc = new DOMDocument();
$doc->loadHTML($input);

# Create an XPath selector
$selector = new DOMXPath($doc);

# Modify values of the style attributes
foreach($selector->query('//@style') as $style) {
    $style->nodeValue = preg_replace(
        '/line-height:\s*[0-9]+(\.[0-9]+)?px\s*;?/',
        'HELLO;',
        $style->nodeValue
    );
}

# Output the modified document
echo $doc->saveHTML();

使用DOM 和XPath 的优点是即使HTML 内容变得怪异,您也可以可靠地访问任何嵌套级别的样式属性。如果 HTML 结构将来发生变化,或者您想更接近地指定应该更改的样式属性,也很容易维护。

以下面的查询为例,它只选择 &lt;span&gt; 标记的样式属性,该标记具有类 even 并且是 div 和 id="foo" 的子级(在任何嵌套级别)。

//div[@id="foo"]//span[contains(@class, "even")]/@style

如果您尝试使用正则表达式,您将获得很多乐趣! :)


关于CSS 部分。我决定为此使用正则表达式,因为我能想到的唯一可能破坏正则表达式的东西是:

<span style="background:url('line-height:2px');">

由于line-height:2px 是一个有效的 UNIX 文件名,上述情况是可能的。但是,嘿! :) 如果你真的很在意,你需要使用 CSS 解析器来完成这项工作。

【讨论】:

    【解决方案2】:

    你可以在这里使用\K。\K resets the starting point of the reported match. Any previously consumed characters are no longer included in the final match

    style=.*?\Kline-height.*?(?=[;"])
    

    试试这个。See demo.

    这将确保只有line=height... 将被替换,并且它前面也有style=

    【讨论】:

    • 真棒甚至更好的解决方案:)
    【解决方案3】:

    这是你想要的正则表达式

    (line-height:\s+\d+\.\d+px)
    

    Debuggex Demo

    【讨论】:

    • 但我也想确保前面有样式标签,就像我在正则表达式中所做的那样。
    • 你能写出预期的输出吗?应该是
    • 500.00dkk
    • 吗?
    【解决方案4】:

    我发现我可以使用每个组的引用将该组插入到替换中,所以我没有丢失 color:red 部分。

    preg_replace ('/(?<=style=["])(.*)(line-height.*?)[;"]/', '$1HELLO', $input);
    

    这给了我想要的结果。

    【讨论】:

      猜你喜欢
      相关资源
      最近更新 更多
      热门标签