【问题标题】:regex expression for escaped quoted string won't work in php's preg_match_all转义引号字符串的正则表达式在 php 的 preg_match_all 中不起作用
【发布时间】:2010-12-21 21:54:25
【问题描述】:

我正在尝试匹配一段文本中的带引号的字符串,并允许在其中包含转义的引号。我在在线测试器中尝试了这个正则表达式,它运行良好。但是,当我在 preg_match_all 中尝试时,它在第一个转义字符串处失败。

代码如下:

$parStr = 'title="My Little Website"
    year="2007"
    description="Basic website with ..."
    tech="PHP, mySQL"
    link="<a href=\"http://test.com\">test.com</a>"
';
$matches = array();

preg_match_all('/(\w+)\s*=\s*"(([^\\"]*(\\.)?)*)"/', $parStr, $matches, PREG_SET_ORDER); // Match[4][0] is 'link="<a href=\"'

最后一次匹配失败,只匹配到第一个转义引号。当我在http://www.regexplanet.com/simple/index.html 尝试这个表达式时,它运行良好。

正则表达式的相关部分是:

"(([^\\"]*(\\.)?)*)"

应该吃掉所有导致转义引号或引号的文本,然后吃掉可选的转义引号,该过程重复0次或更多次,直到找到非转义引号,其中匹配完成.

为什么这在 php 中不起作用?为什么它不起作用,应该如何解决?

【问题讨论】:

  • 在 $parStr 中,你想找到什么?

标签: php regex quotes escaping


【解决方案1】:

我在 Linux Fedora PHP 5.2.6 上尝试过,它似乎工作正常。输出是:

[wally@zf ~]$ php -f z.php
title="My Little Website"
    year="2007"
    description="Basic website with ..."
    tech="PHP, mySQL"
    link="<a href=\"http://test.com\">test.com</a>"

【讨论】:

  • 很好奇,因为它不适用于我的 - Ubuntu 9.10 和 PHP 5.2.10
【解决方案2】:

这样怎么样?

preg_match_all('/(\w+)\s*=\s*"((?:.*?\"?)*)"/', $parStr, $matches, PREG_SET_ORDER); 

它给了我这样的感觉

[1] => link
[2] => <a href=\"http://test.com\">test.com</a>

在 [] 内,一切都视为单个字符,

对于[^\\"],不代表EXCEPT \",而是代表EXCEPT \ AND EXCEPT "

更新同一行中的多个值

preg_match_all('/(\w+)\s*=\s*"((?:[^\\\]*?(?:\\\")?)*?)"/', $parStr, $matches, PREG_SET_ORDER); 

源字符串,样本

$parStr = 'title="我的小网站" 年份="2007" description="基本网站..." 技术="PHP, mySQL" 技术="PHP, mySQL" 链接="http://test.com\">test.com" 链接="http://test.com\">test.com" tech="PHP, mySQL" ';

匹配项

Array
(
    [0] => Array
        (
            [0] => title="My Little Website"
            [1] => title
            [2] => My Little Website
        )

    [1] => Array
        (
            [0] => year="2007"
            [1] => year
            [2] => 2007
        )

    [2] => Array
        (
            [0] => description="Basic website with ..."
            [1] => description
            [2] => Basic website with ...
        )

    [3] => Array
        (
            [0] => tech="PHP, mySQL"
            [1] => tech
            [2] => PHP, mySQL
        )

    [4] => Array
        (
            [0] => tech="PHP, mySQL"
            [1] => tech
            [2] => PHP, mySQL
        )

    [5] => Array
        (
            [0] => link="<a href=\"http://test.com\">test.com</a>"
            [1] => link
            [2] => <a href=\"http://test.com\">test.com</a>
        )

    [6] => Array
        (
            [0] => link="<a href=\"http://test.com\">test.com</a>"
            [1] => link
            [2] => <a href=\"http://test.com\">test.com</a>
        )

    [7] => Array
        (
            [0] => tech="PHP, mySQL"
            [1] => tech
            [2] => PHP, mySQL
        )

)

就个人而言,我觉得用正则表达式解析 HTML,不是很喜欢,但我没有看到任何其他选项可以建议你,所以它只是一种快速而肮脏的方式。对于大项目或大文件,我建议你找到一个真正的解析器。

【讨论】:

  • 当一行中有多个带引号的字符串时,此代码不起作用。它无法找到第二个结束报价。我认为问题出在 \"? 中,? 仅与 "有关,但与 \. 无关
【解决方案3】:

我不知道为什么它不适用于一个特定版本的 php,但是使用非贪婪匹配的想法,我想出了这个有效的字符串:

"(.*?[^\\\])"

它非贪婪地匹配所有内容,直到遇到一个前面没有转义字符的 dbl-quote。由于某些特殊原因,需要三个反斜杠,否则 php 会抱怨括号不匹配。我认为它的存在需要在括号前加上反斜杠,但我不确定。谁能确认为什么需要三个反斜杠?

/编辑空白限制

【讨论】:

  • PHP-5.3/Ubuntu-11.10 对我来说非常有用,不过必须先尝试所有其他解决方案。 @Scott:没有第三个反斜杠,结尾插入符号 ] 无法识别
  • 从技术上讲,它可能是四个斜线。双引号中的斜杠转义下一个字符,\\相当于\,从命令行尝试: php -r 'echo "(.*?[^\\])\n";echo "(.*? [^\\\])\n";'
猜你喜欢
  • 2014-09-27
  • 1970-01-01
  • 1970-01-01
  • 2010-09-19
  • 2012-02-03
  • 1970-01-01
  • 2021-06-04
  • 1970-01-01
  • 2012-03-31
相关资源
最近更新 更多