Выражение regex для экранированной строки в кавычках не будет работать в preg_match_all в php - PullRequest
2 голосов
/ 01 декабря 2009

Я пытаюсь сопоставить строки в кавычках внутри фрагмента текста и допускать кавычки внутри него. Я попробовал это регулярное выражение в онлайн-тестере, и оно отлично работает. Тем не менее, когда я пытаюсь сделать это в 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? Почему он не работает и как его исправить?

Ответы [ 3 ]

2 голосов
/ 01 декабря 2009

Я не знаю, почему он не работает для одной конкретной версии php, но, используя идею не жадного совпадения, я нашел эту строку, которая работает:

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

Нечестиво сопоставляет все, пока не встретит dbl-кавычку, которой не предшествует escape-символ. По какой-то особой причине необходимы три обратных слеша или php жалуется на непревзойденную скобку. Я думаю, что его присутствие требует обратной косой черты, чтобы предшествовать скобке, но я не уверен. Кто-нибудь может подтвердить, почему нужны три обратные косые черты?

/ редактировать лимит пробелов

0 голосов
/ 01 декабря 2009

Как насчет этого?

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

Дай мне вот так

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

Внутри [] все считается одним символом,

для [^\\"], это не значит EXCEPT \", его среднее значение EXCEPT \ И EXCEPT "

ОБНОВЛЕНИЕ для нескольких значений в одной строке

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

Исходная строка, образец

$ parStr = 'title = "Мой маленький сайт" год = "2007" description = "Базовый сайт с ..." tech = "PHP, mySQL" tech = "PHP, mySQL" link = "http://test.com\">test.com" link =" 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 с помощью регулярных выражений, не очень-то понравился, но я не вижу другого варианта, чтобы предложить вам, так что это просто быстрый и грязный способ. Для больших проектов или больших файлов я предлагаю вам найти настоящий парсер для этого.

0 голосов
/ 01 декабря 2009

Я попробовал это на 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>"
...