PHP регулярное выражение для сопоставления строк в двойных и / или одинарных кавычках внутри строки - PullRequest
0 голосов
/ 10 июля 2010

Я работаю над шаблоном класса и у меня возникла проблема при попытке разобрать список строк в кавычках из списка аргументов строки.Возьмем, к примеру, строку:

$string = 'VAR_SELECTED, \'Hello m\'lady\', "null"';

У меня возникла проблема с поиском регулярного выражения, которое извлекает строки "Hello m'lady" и "null".Самый близкий у меня есть

$string = 'VAR_SELECTED, \'Hello m\'lady\', "null", \'TE\'ST\'';
preg_match_all('/(?:[^\']|\\\\.)+|(?:[^"]|\\\\.)+/', $string, $matches);
print_r($matches);

Какие выходы:

Array
(
    [0] => Array
        (
            [0] => VAR_SELECTED, 
            [1] => 'Hello m'lady', 
            [2] => "null", 
            [3] => 'TE'ST'
        )

)

Однако более сложный случай:

$string = 'VAR_SELECTED, \'Hello "Father"\', "Hello \'Luke\'"';
preg_match_all('/(?:[^\']|\\\\.)+|(?:[^"]|\\\\.)+/', $string, $matches);
print_r($matches);  

выходов:

Array
(
    [0] => Array
        (
            [0] => VAR_SELECTED, 
            [1] => 'Hello 
            [2] => "Father"
            [3] => ', 
            [4] => "Hello 
            [5] => 'Luke'
            [6] => "
        )

)

Может кто-нибудь помочь мне решить эту проблему?Являются ли несколько регулярных выражений способом продвижения вперед?

Редактировать Может быть, было бы проще заменить запятые в строках на заполнитель, а затем разбить строки на разнесение?

Редактировать 2 Просто подумал о простой небезопасной опции (которую я не собираюсь использовать), но генерирует ошибку E_NOTICE.

$string = 'return array(VAR_SELECTED, \'Hello , "Father"\', "Hello \'Luke\'4");';
$string = eval($string);
print_r($string);

Ответы [ 3 ]

3 голосов
/ 10 июля 2010

Попробуйте:

/(?<=^|[\s,])(?:(['"]).*?\1|[^\s,'"]+)(?=[\s,]|$)/

Или, как строковый литерал PHP в одинарных кавычках:

'/(?<=^|[\s,])(?:([\'"]).*?\1|[^\s,\'"]+)(?=[\s,]|$)/'

Это регулярное выражение дает желаемый результат, но я думаю, что вы собираетесьэто неправильно.Обычно, если строка в кавычках должна содержать буквальный символ кавычки, кавычка экранируется либо с обратной косой чертой, либо с другой кавычкой.Вы этого не делаете, поэтому мне пришлось использовать хрупкий хак, основанный на обходных путях.Вы уверены, что данные не должны выглядеть так?

$string = 'VAR_SELECTED, \'Hello m\\'lady\', "null"';

$string = 'VAR_SELECTED, \'Hello "Father"\', "Hello \\'Luke\\'"';

Если подумать, разве в PHP нет встроенной поддержки данных CSV?

1 голос
/ 10 июля 2010

Вот как я бы это сделал:

Разбейте задачу на этапы, которые вы хотите выполнить:

1.) Разбейте строку на запятые.

For 'VAR_SELECTED, \'Hello m\'lady\', "null"' this gives me
[0]=>"VAR_SELECTED"
[1]=>" \'Hello m\'lady\'"
[2]=>" "null""

For 'VAR_SELECTED, \'Hello "Father"\', "Hello \'Luke\'"' this gives me
[0]=>"VAR_SELECTED"
[1]=>" \'Hello "Father"\'"
[2]=>" "Hello \'Luke\'""

2.) Запустите Trim на всех трех, чтобы избавиться от любых пробелов

For 'VAR_SELECTED, \'Hello m\'lady\', "null"' this gives me
[0]=>"VAR_SELECTED"
[1]=>"\'Hello m\'lady\'"
[2]=>""null""

For 'VAR_SELECTED, \'Hello "Father"\', "Hello \'Luke\'"' this gives me
[0]=>"VAR_SELECTED"
[1]=>"\'Hello "Father"\'"
[2]=>""Hello \'Luke\'""

3.) Запустите str_replace ("\", "", $ text), чтобы избавиться от косой черты.(удалите пробелы ... добавлены только для удобства чтения, так что это должен быть пустой слеш и "пустая" строка)

For 'VAR_SELECTED, \'Hello m\'lady\', "null"' this gives me
[0]=>"VAR_SELECTED"
[1]=>"'Hello m'lady'"
[2]=>""null""

For 'VAR_SELECTED, \'Hello "Father"\', "Hello \'Luke\'"' this gives me
[0]=>"VAR_SELECTED"
[1]=>"'Hello "Father"'"
[2]=>""Hello 'Luke'""

4.) Запустите обрезку снова, только обрезку ($ text, "'" ") (убрать пробелы ... добавлено только для удобства чтения)

For 'VAR_SELECTED, \'Hello m\'lady\', "null"' this gives me
[0]=>"VAR_SELECTED"
[1]=>"Hello m'lady"
[2]=>"null"

For 'VAR_SELECTED, \'Hello "Father"\', "Hello \'Luke\'"' this gives me
[0]=>"VAR_SELECTED"
[1]=>"Hello "Father""
[2]=>"Hello 'Luke'"

Я не проверял это, но логика звучит правильно. Быстрый и грязный способ проверить 98% всех регулярных выражений (по моему опыту)) должен использовать http://rubular.com/ Это отличный сайт. Обычно, если он начинает задыхаться от регулярного выражения, это мой первый признак того, что я должен решить проблему еще больше (это просто мнение ~ Донс огнестойкий костюм ~)

0 голосов
/ 10 июля 2010

Вы хотите использовать обратную ссылку в строке соответствия.

preg_match_all('@([\'"]).*[^\\\\]\1@', $string, $matches);

Это начнет совпадать с первым экземпляром "или", а затем совпадет с самой длинной строкой, которая заканчивается совпадением "или", что не является экранированным.

Array (
[0] => Array
    (
        [0] => 'Hello m'lady', "null", 'TE'ST'
    )

[1] => Array
    (
        [0] => '
    )
...