PHP preg_match_all выражение - PullRequest
       9

PHP preg_match_all выражение

1 голос
/ 11 января 2011

У меня практически нет опыта в regx, но я стараюсь изо всех сил.

У меня есть такая строка:

$fString = "Name=Sök,Value=2,Title=Combine me,Options=[Item1=1,Item2=2,Item3=3]";

Я хочу получить массив, похожий на этот:

Array[0] = "Name=Sök"
Array[1] = "Value=2"
Array[2] = "Title=Combine me"
Array[3] = "Options=[Item1=1,Item2=2,Item3=3]"

Что мне удалось сделать до сих пор:

preg_match_all("/[^,]*[\w\d]*=[^,]*/",$fString,$Data);

Но я не могу понять, как исправить последний «вариант».

Array ( [0] => Array ( [0] => Name=S�k [1] => Value=2 [2] => Title=Combine me [3] => Options=[Item1=1 [4] => Item2=2 [5] => Item3=3] ) )

... и почему результат является массивом внутри массива?!?


[EDIT]

Полагаю, мне нужно объяснить всю идею того, что я здесь пытаюсь сделать, я не уверен, что я на правильном пути.

Я создал несколько классов, в которых я храню все «постоянные» переменные в массиве. У меня есть функция, которая сериализует этот массив, чтобы я мог храниться в базе данных.

Я знаю все о функции serialize (), но я делаю некоторую фильтрацию, поэтому я не могу использовать ее как есть, и я также предпочитаю сделать ее более читаемой для ручного редактирования. Этот массив может иметь вложенные массивы внутри, которые должны быть сохранены. Когда я читаю все это из базы данных, исходный массив должен быть создан снова.

У меня все это работало с командой eval (), но я столкнулся с проблемой, когда я вложил массивы из-за того, что символы "или" разбивали основную внешнюю строку. Поэтому этот подход был попыткой сериализации всего без вложенных строк необходимо сохранить.

Так что, если я могу решить вложенные данные с помощью preg_match_all, я там, в противном случае мне нужно найти другое решение.

Я полагаю, что необходимо также экранировать данные, такие как, и []

Ответы [ 5 ]

2 голосов
/ 11 января 2011

Вот функция, которая будет делать в основном то, что вам нужно:

function explode_me($str) {
    $a = array();
    $v = "";
    $ignore = false;
    for ($i = 0; $i < strlen($str); $i++) {
        if ($str[$i] == ',' && !$ignore) {
            $a[] = $v;
            $v = "";
        }
        else if ($str[$i] == '[' && !$ignore) {
            $ignore = true;
            $v .= $str[$i];
        }
        else if ($str[$i] == ']' && $ignore) {
            $ignore = false;
            $v .= $str[$i];
        }
        else {
            $v .= $str[$i];
        }
    }
    $a[] = $v;
    return $a;
}

Чтобы проверить это:

$str = "Name=Sök,Value=2,Title=Combine me,Options=[Item1=1,Item2=2,Item3=3]";
$a = explode_me($str);

print_r($a);

который печатает:

Array
(
    [0] => Name=Sök
    [1] => Value=2
    [2] => Title=Combine me
    [3] => Options=[Item1=1,Item2=2,Item3=3]
)
2 голосов
/ 11 января 2011
(\w+)=(\[[^\]]+\]|[^,]+)

Это разбивается как:

(\w+)        # a word (store in match group 1)
=            # the "=" character
(            # begin match group 2
  \[         #   a "[" character
  [^\]]+     #   anything but "]" character
  \]         #   a "]" character
  |          #   or...
  [^,]+      #   anything but a comma
)            # end match group 1

Применить с preg_match_all():

$fString = "Name=Sök,Value=2,Title=Combine me,Options=[Item1=1,Item2=2,Item3=3]";

$matches = array();
preg_match_all("/(\\w+)=(\\[[^\\]]+\\]|[^,]+)/", $fString, $matches);

Что приводит к чему-то более подробному, чем вы хотели:

Array
(
    [0] => Array
        (
            [0] => Name=Sök
            [1] => Value=2
            [2] => Title=Combine me
            [3] => Options=[Item1=1,Item2=2,Item3=3]
        )

    [1] => Array
        (
            [0] => Name
            [1] => Value
            [2] => Title
            [3] => Options
        )

    [2] => Array
        (
            [0] => Sök
            [1] => 2
            [2] => Combine me
            [3] => [Item1=1,Item2=2,Item3=3]
        )

)

$result[0] - это то, что вы хотели. $result[1] и $result[2] являются именами и значениями свойств отдельно, что позволяет вам использовать их сразу, вместо того, чтобы делать дополнительный шаг, который разбивает такие вещи, как "Options=[Item1=1,Item2=2,Item3=3]" на правильные =.

1 голос
/ 11 января 2011

Итак, вот другой подход. Это мини-парсер для вложенных структур. Адаптируйте регулярные выражения, если вам нужны escape-коды.

function parse(&$s) {
    while (strlen($s) && preg_match("/^(.*?)([=,\[\]])/", $s, $m)) {
        $s = substr($s, 1 + strlen($m[1]));
        switch ($m[2]) {
            case "=":
               $key = $m[1];
               break;
            case ",":
               if (!isset($r[$key])) {
                  $r[$key] = $m[1];
               }
               break;
            case "[":
               $r[$key] = parse($s);
               break;
            case "]":
               return $r;
        }
    }
    if ($s) { $r[$key] = $s; } // remainder
    return $r;
}
1 голос
/ 11 января 2011

Это проблема, которая больше подходит для анализа, чем для извлечения регулярных выражений. Но вы можете выделить специальный случай, чтобы он работал:

preg_match_all("/(\w+)=( \w[^,]+ | \[[^\]]+\] )/x", $str, $m);
$things = array_combine($m[1], $m[2]);

Даст вам PHP-переменную наподобие (но вы можете получить доступ к $ m [0] для непарсированных строк):

[Name] => Sök
[Title] => Combine me
[Options] => [Item1=1,Item2=2,Item3=3]

Вы можете повторно применить функцию на Options, чтобы взорвать это тоже.

Хитрость опять в том, чтобы различать \w все, что начинается с буквы, и \[...\] вложенные опции. Там нужно просто сделать так, чтобы ^] соответствовало всем не закрывающим скобкам, и все.

1 голос
/ 11 января 2011

Если бы вы могли изменить разделители между элементами (где указано Item1 = 1, Item2 = 2, Item3 = 3 на что-то вроде Item1 = 1 | Item2 = 2 | Item3 = 3), вы могли бы легко использовать explode(',',$fString) для преобразовать строку в массив.

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

$newstr = str_replace(',Item','|Item',$fString);
$newarray = explode(',',$newstr);

$newarray будет выглядеть так:

Array[0] = "Name=Sök"
Array[1] = "Value=2"
Array[2] = "Title=Combine me"
Array[3] = "Options=[Item1=1|Item2=2|Item3=3]"
...