【问题标题】:Regex for attribute value having quotes in between same as the enclosing quotes带有引号的属性值的正则表达式与封闭引号之间的引号相同
【发布时间】:2022-01-18 11:35:12
【问题描述】:

字符串多次出现 alt attr 键值。在 alt attr 的值中是包含双引号 (") 的字符串。这个双引号使值在第一次出现双引号时终止,而不是取完整值。请帮助修改正则表达式以实现完整的 alt 值

$text = 'advcd<img loading="lazy" class="abcd pqr" alt="chi-phi-sinh-o-benh-v"ien-dai-hoc-y-duoc-co-so-2" attr="val"><img loading="lazy" class="abcd pqr" alt="abcd-sinh-o-benh-"ien-dai-hoc-y-duoc-co-so-3">sdfs';

preg_match_all('/(alt)=(["\'][^"\']*["\'])/i', $text, $matches);

if (count($matches) > 1) {
    print_r($matches);
}

电流输出:

Array
(
    [0] => Array
        (
            [0] => alt="chi-phi-sinh-o-benh-v\"
            [1] => alt="abcd-sinh-o-benh-\"
        )

    [1] => Array
        (
            [0] => alt
            [1] => alt
        )

    [2] => Array
        (
            [0] => "chi-phi-sinh-o-benh-v\"
            [1] => "abcd-sinh-o-benh-\"
        )

)

预期输出:

Array
(
    [0] => Array
        (
            [0] => alt="chi-phi-sinh-o-benh-v"ien-dai-hoc-y-duoc-co-so-2"
            [1] => alt="abcd-sinh-o-benh-"ien-dai-hoc-y-duoc-co-so-3"
        )

    [1] => Array
        (
            [0] => alt
            [1] => alt
        )

    [2] => Array
        (
            [0] => "chi-phi-sinh-o-benh-v"ien-dai-hoc-y-duoc-co-so-2"
            [1] => "abcd-sinh-o-benh-"ien-dai-hoc-y-duoc-co-so-3"
        )

)

【问题讨论】:

  • 改用 XML 解析器。

标签: php regex


【解决方案1】:

您可以将属性值中的"转换为&amp;quot;,然后使用dom解析器来获取alt值更容易:

$text = 'advcd<img loading="lazy" class="abcd pqr" alt="chi-phi-sinh-o-benh-v&quot;ien-dai-hoc-y-duoc-co-so-2" attr="val"><img loading="lazy" class="abcd pqr" alt="abcd-sinh-o-benh-&quot;ien-dai-hoc-y-duoc-co-so-3">sdfs';
$dom = new DOMDocument();
$dom->loadHTML($text, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xpath = new DOMXpath($dom);

foreach($xpath->evaluate("//img/@alt") as $i) {
    echo $i->nodeValue . PHP_EOL;   
}

输出

chi-phi-sinh-o-benh-v"ien-dai-hoc-y-duoc-co-so-2
abcd-sinh-o-benh-"ien-dai-hoc-y-duoc-co-so-3

对示例字符串使用正则表达式:

  • (alt)= 捕获 group 1,匹配 alt 后跟 =
  • ( 捕获第 2 组
    • ".*?"" 匹配,然后是最少的字符,直到下一个 "
    • (?= 积极前瞻
      • \s* 匹配可选的空白字符
      • (?:[^\s=]+="|&gt;) 匹配除= 之外的任一非空白字符,直到匹配=" 或匹配&gt;
    • ) 关闭前瞻
  • )关闭第二组

Php demo | regex demo

$text = 'advcd<img loading="lazy" class="abcd pqr" alt="chi-phi-sinh-o-benh-v"ien-dai-hoc-y-duoc-co-so-2" attr="val"><img loading="lazy" class="abcd pqr" alt="abcd-sinh-o-benh-"ien-dai-hoc-y-duoc-co-so-3">sdfs';

preg_match_all('/(alt)=(".*?"(?=\s*(?:[^\s=]+="|>)))/i', $text, $matches);

if (count($matches) > 1) {
    print_r($matches);
}

输出

Array
(
    [0] => Array
        (
            [0] => alt="chi-phi-sinh-o-benh-v"ien-dai-hoc-y-duoc-co-so-2"
            [1] => alt="abcd-sinh-o-benh-"ien-dai-hoc-y-duoc-co-so-3"
        )

    [1] => Array
        (
            [0] => alt
            [1] => alt
        )

    [2] => Array
        (
            [0] => "chi-phi-sinh-o-benh-v"ien-dai-hoc-y-duoc-co-so-2"
            [1] => "abcd-sinh-o-benh-"ien-dai-hoc-y-duoc-co-so-3"
        )

)

【讨论】:

  • 您的正则表达式解决方案对我有用,非常感谢您的时间和投入
【解决方案2】:

似乎结构错误,应该在" 之前添加\。但是下面的正则表达式会导致一个解决方案。

(alt)=((["\']).*?[^\\]\3)(?:\s|>)

\3:匹配到第三个匹配组。使用它是因为该值应以与开头相同的符号结尾("')。

[^\\]\3:在结束引号之前,\ 转义了结束符。

(?:\s|&gt;)"' 之后需要一个空格或“>”。

https://www.phpliveregex.com/p/DmU

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-09
    相关资源
    最近更新 更多