2015-03-13 2 views
1

У меня есть массив, который выглядит следующим образом:значение Группы из массива в соответствии с Regex в PHP

[0] => name { 
[1] => abc 
[2] => def 
[3] => } 
[4] => 
[5] => othername { 
[6] => 123 
[7] => 456 
[8] => 789 
[9] => } 
[10] => 

Как вы можете видеть каждую группу (под каждое имя) может иметь разное количество линий и различные элементы в них но каждая группа начинается с того же синтаксиса регулярных выражений и заканчивается закрытием} и пустой строкой после этого.

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

Так что я хочу получить:

array(
    array('name {', 'abc', 'def', '}'), 
    array('othername {', '123', '456', '789', '}') 
) 

Как я могу подойти к этому? Заранее спасибо.

+0

Так что вы хотите 'abcdef' и' 123456789' двух переменных? – chris85

+0

На самом деле мне нужно было бы что-то вроде 'Array [0] ([0] => name {, [1] => abc, [2] => def, [3] =>}), Array [1] ([0] => othername {, [1] => 123, [2] => 456, [3] => 789, [4] =>}) 'поэтому я могу затем вызвать каждый массив с ним, имеющим все его значения , – CesarA

+0

Похоже, вы сделали токены, теперь просто разобрали его :) Вы не можете делать это только с регулярными выражениями, создайте небольшую машину состояний. – Halcyon

ответ

2

Clicquot избил меня, но я не уверен, что его работы/протестированы. Вот мое решение

<?php 
$array = array('0' => 'name {', '1' => 'abc', '2' => 'def', '3' => "}\n", '4' => "\n", 
'5' => 'othername {', 
'6' => '123', 
'7' => '456', 
'8' => '789', 
'9' => '}', 
'10' => "\n"); 
$string = array(); 
$count = 0; 
foreach($array as $value){ 
    $value = trim($value); 
    $pos = strpos($value, '{'); 
    if ($pos !== false) { 
     $count++; 
    } 
    if(!empty($value)) { 
     $string[$count][] = $value; 
    } 
} 
print_r($string); 
+0

Спасибо! Работал с места в карьер! – CesarA

+1

'// это глупо, но true didnt work' omg, вы можете написать' if (strpos ($ value, '{')! == false) ' –

+0

Ha, истинное спасибо @CasimiretHippolyte Простые вещи всегда меня уклоняют. – chris85

-1

Это не настоящая вещь. То, что вы хотите сделать, это перебрать массив и проверить каждый элемент. Вы проверили значение там для '{' или '}'. Когда вы видите открывающую скобку, вы должны установить ключ в свой «сконденсированный» массив, который хотите индексировать, а затем проверить последующие элементы для закрывающей скобки. Когда вы увидите закрывающую скобку, вы измените ключ, который вы индексируете, в свой «сконденсированный» массив или что-то еще и начинаете заново. Когда значение не является скобкой, добавьте его. Это будет выглядеть примерно так (извините за плохой PHP):

$big_array = array(); 
$temp_key = NULL; 
foreach (array as $key => $value) { 
    if (strpo($value, '{')) { 
     $big_array[$key] = array(); 
     $temp_key = $key; 
    } else if (strpos($value, '}')) { 
     $temp_key = NULL; 
    } else { 
     $big_array[$temp_key].append($value); // or whatever 
    } 

} 

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

+0

Нет, я люблю жить опасно. –

+0

Это хороший способ, но в следующий раз попробуйте написать рабочий php-код. –

0

Возможно, этот код является тем, о чем вы просили. Но я никогда не буду использовать его сам. Если вы попытаетесь создать парсер кода, вы shuold посмотрите на parsing-trees с помощью «грамматики» или синтаксического анализа. Он входит в состав parsing и компиляторов. На слайде показано, как работает компилятор или интерпретатор. Если вы только предназначаетесь для представления своих данных для достижения определенной цели, возможно, вы можете посмотреть на такие форматы, как json. Вы должны всегда указывать в одном предложении, какова ваша общая цель, прежде чем задавать конкретный вопрос. enter image description here (извините за немецким)

Вопросов ниже коды, что изменения синтаксиса могут взломать код, и вы сильно voulnerable, потому что код изменяет ваше содержимое переменной PHP касательно содержимые вашего массива.

Если вы обрабатываете файл с кодом, я рекомендую вам также обрабатывать его в пространстве, вместо того, чтобы сначала сохранить его в массив (который стоит больше памяти).

<?php 
$syntaxArray = array(
    0 => 'name {', 
    1 => 'abc', 
    2 => 'def', 
    3 => '}', 
    4 => 'othername {', 
    5 => '123', 
    6 => '456', 
    7 => '789', 
    8 => '}' 
); 

$regex_open_array = '-(\w+)\s*{-'; 
$array_open = false; 
foreach($syntaxArray as $line){ 
    $matches = array(); 
    if(preg_match($regex_open_array, $line, $matches)){ 
     if($array_open){ 
      /*recursive array creations do not work - if that's what you need put it in the comments*/ 
      throw new RuntimeException('An array can not be open while the previous array is not closed'); 
     } 
     $array_open = true; 
     /*create an array variable 
     * .... 
     * isolate the variable name 
     */ 
     $currentArray = $matches[1]; 


     /*you can either create a new variable in your php code with the array name or use a big array and use the name as key 
     * $big_array[$name] = array(); 
     * using this solution every array name must be only used once. 
     * of course you can use a name twice if you first check prior to creating a new array if the key is already in use. 
     */ 


     /*creates a variable with the given name. Must not overwrite an other arrays name like $syntaxArray*/ 
     $$currentArray = array(); 
    }else if($line == '}'){ 
     /*the closing string could be wrapped with trim() or matched with a regex but I followed your example*/ 
     $array_open = false; 
    }else{ 
     if(!$array_open){ 
      throw new RuntimeException('There is not array currently open'); 
     } 
     $arr = &$$currentArray; 
     $arr[] = $line; 

    } 
} 

var_dump($name); 
var_dump($othername); 

Выходы:

array(2) { [0]=> string(3) "abc" [1]=> string(3) "def" } array(3) { [0]=> string(3) "123" [1]=> string(3) "456" [2]=> string(3) "789" } 
+0

Использование 'preg_match' здесь слишком велико, вы можете сделать то же самое с простой' strpos', даже если вы не проверяете имя раньше. –

+0

Это может ускорить код, но опять же ограничивает (пробелы) варианты. –

Смежные вопросы