Повторите захват Regex - PullRequest
       8

Повторите захват Regex

0 голосов
/ 11 февраля 2019

Я пытался заставить это Regex работать, и я чувствую, что почти у меня это есть, но я не уверен, как получить желаемые результаты.Я использую фиктивную структуру данных, которая напоминает объект JSON, и пытаюсь проанализировать параметры.

Структура напоминает группы и параметры, такие как: group_label:id{option_1:id,option_2:id ... }

Выражение, которое я имеюдо сих пор получается

(?:(?:(?<group_name>[a-zA-Z0-9 _]+?):(?<group_id>[0-9]+?){(?:(?:(?<option_name>.+?):(?<option_id>.+?))+?,?)+?},?))+?

, и я использую следующие тестовые данные:

My Interests:379{Commercial:0,Consumer:1,Wholesale Reseller:2},Test Group:1234{Test One:1,Test 2:2}

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

https://regex101.com/r/GkW57Y/1

Он также ломается, если я пытаюсь указать начало и конец строки, так что я уверен, что это намек на то, что что-то я делаю неправильно, но я не эксперт по регулярным выражениям, и я бегукороче по времени.Как всегда, любой совет всегда ценится!

1 Ответ

0 голосов
/ 11 февраля 2019

Вот регулярное выражение, которое будет извлекать группы и параметры, просто просматривая различные функции (группы заканчиваются на {, параметры начинаются с { или , и заканчиваются , или }):

(?<group_name>[a-zA-Z0-9 _]+):(?<group_id>[0-9]+)(?={)|(?<=[{,])(?<option_name>[^:]+):(?<option_id>[^,}]+)(?=[,}])

В PHP вы можете использовать его таким образом, чтобы получить списки groups и options:

$string = 'My Interests:379{Commercial:0,Consumer:1,Wholesale Reseller:2},Test Group:1234{Test One:1,Test 2:2}';
$regex = '(?<group_name>[a-zA-Z0-9 _]+):(?<group_id>[0-9]+)(?={)|(?<=[{,])(?<option_name>[^:]+):(?<option_id>[^,}]+)(?=[,}])';
preg_match_all("/$regex/", $string, $matches);
//print_r($matches);
$groups = array_combine(array_filter($matches['group_name']), array_filter($matches['group_id'], function ($v) { return $v !== '';}));
$options = array_combine(array_filter($matches['option_name']), array_filter($matches['option_id'], function ($v) { return $v !== '';}));
print_r($groups);
print_r($options);

Вывод:

Array (
    [My Interests] => 379
    [Test Group] => 1234
)
Array (
    [Commercial] => 0
    [Consumer] => 1
    [Wholesale Reseller] => 2
    [Test One] => 1
    [Test 2] => 2 
)

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

$output = array();
for ($i = 0; $i < count($matches['group_name']); $i++) {
    if ($matches['group_name'][$i] != '') {
        // new group
        $this_group = $matches['group_name'][$i];
        $output[$this_group] = array('id' => $matches['group_id'][$i]);
    }
    else {
        // option for this group
        $output[$this_group]['options'][$matches['option_name'][$i]] = $matches['option_id'][$i];
    }
}
print_r($output);

Вывод:

Array (
    [My Interests] => Array (
        [id] => 379
        [options] => Array (
            [Commercial] => 0
            [Consumer] => 1
            [Wholesale Reseller] => 2
        )
    )
    [Test Group] => Array (
        [id] => 1234
        [options] => Array (
            [Test One] => 1
            [Test 2] => 2
         )
    ) 
)

Или, возможно, это может быть более полезным:

$output = array();
$this_group = -1;
for ($i = 0; $i < count($matches['group_name']); $i++) {
    if ($matches['group_name'][$i] != '') {
        // new group
        $this_group++;
        $output[$this_group] = array('name' => $matches['group_name'][$i], 'id' => $matches['group_id'][$i]);
    }
    else {
        // option for this group
        $output[$this_group]['options'][$matches['option_name'][$i]] = $matches['option_id'][$i];
    }
}
print_r($output);

Выход:

Array (
    [0] => Array (
        [name] => My Interests
        [id] => 379
        [options] => Array (
            [Commercial] => 0
            [Consumer] => 1
            [Wholesale Reseller] => 2
        )
    )
    [1] => Array (
        [name] => Test Group
        [id] => 1234
        [options] => Array (
            [Test One] => 1
            [Test 2] => 2
         )
    ) 
)

Демонстрация на 3v4l.org

...