2016-12-21 4 views
0

Мне нужно передать данные в массив блоками, как я могу это сделать? Нужно ли использовать регулярное выражение? Мой скрипт дает мне ошибки, потому что я не могу отделить его, как я желаю. У кого-нибудь есть идеи?Как разобрать строку на многомерный массив (regex?)

данных:

~0 
11111111 
~1 
222222222 
~2 
3333333333 

     ~end 
~0 
aaaaaaaaaaa 
~1 
bbbbbbbbbb 
~2 
cccccccccc 
~3 
ddddddddddd 

     ~end 



~0 
yyyyyyyyyyy 
xxxxxxxx 
ffffffffff 
~1 
rrrrrrrrrrrr 
     ~end 

мне это нужно так:

Array ( 
    [0] => Array 
       (
        [0] => 11111111 

        [1] => 222222222 

        [2] => 3333333333 


       ) 

     ), 

    [1] => Array 
       (
        [0] => aaaaaaaaaaa 

        [1] => bbbbbbbbbb 

        [2] => cccccccccc 

        [3] => ddddddddddd 
       ) 

     ), 

    [2] => Array 
        (
         [0] => yyyyyyyyyyy 
xxxxxxxx 
ffffffffff 

         [1] => rrrrrrrrrrrr 

       ) 

     ), 



) 

Мой код (неудовлетворительно):

$texto = "~0 
11111111 
~1 
222222222 
~2 
3333333333 

     ~end 
~0 
aaaaaaaaaaa 
~1 
bbbbbbbbbb 
~2 
cccccccccc 
~3 
ddddddddddd 

     ~end 



~0 
yyyyyyyyyyy 
xxxxxxxx 
ffffffffff 
~1 
rrrrrrrrrrrr 
     ~end"; 

preg_match_all("/(?ms)^~0.*?~end/", $texto, $coincidencias); 

foreach ($coincidencias[0] as $bloque){ 
    preg_match_all("/\~.*\n/", $bloque, $sub_bloques); 
    $hola[] = $sub_bloques; 
} 
+0

Я не уверен, что я правильно понял требования, не могли бы вы подтвердить? «Каждая непустая строка NOT, начинающаяся с caracter ~, должна быть одной записью в массиве« – Dragos

+0

@Dragos от «~ 0» до «~ end» - это один блок (теперь они 3 блока) и на каждый текст блока ~ 0, ~ 1, ~ 2 до позиции массива (только текст) –

+0

Я предпочел бы работать в 2 этапа: 1. '$ level1 = explode ('~ end', $ data)' 2. 'foreach ($ level1 в качестве $ subItem) {$ matches = preg_match_all ('^ (\ w *) $', $ subItem)} ' – Dragos

ответ

3

Вот один не-регулярное выражение так: разбить строку в строки и перебирать их. Проверьте условия, которые вы указали, и добавьте каждую строку в подматрицу, если она соответствует условиям. Затем, когда вы доберетесь до линии ~end, добавьте подматрицу в основной массив.

$sub_bloques = []; 
$hola = []; 

foreach(array_map('trim', explode("\n", $texto)) as $line) { 
    if ($line && substr($line, 0, 1) !== '~') { 
     $sub_bloques[] = $line; 
    } 
    if ($line == '~end') { 
     $hola[] = $sub_bloques; 
     $sub_bloques = []; 
    } 
} 

Для решения регулярных выражений, начните взрываются на ~end разбить основной текст на разделы, затем preg_match_all на секции, чтобы найти строки, которые удовлетворяют заданным условиям.

foreach (explode('~end', $texto, -1) as $section) { 
    preg_match_all('/\n *(?!~)(\w+)/', $section, $matches); 
    if ($matches[1]) $result[] = $matches[1]; 
} 

(?!~) является отрицательным, чтобы исключить просмотр назад строки, которые начинаются с ~. Может быть, есть способ сделать все это с одним большим крутым регулярным выражением, но я не так хорош в этом.

+0

это отлично, но с (~ 0 гггггггггггггйайайай xxxxxxxx ffffffffff ) ist один текст, а не новая строка, текст имеет больше \ n .... –

+0

Прошу прощения, я не уверен, что понимаю, что вы имеете в виду.Не могли бы вы попытаться объяснить это мне немного больше? –

+0

последний блок ~ 0 yyyyyyyyyyy XXXXXXXX FFFFFFFFFF , есть ист 1 текст, а не 3 позиций –

0

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

Код:

// This delivers the sub-blocks in their relative blocks as requested in the OP 
foreach (preg_split('/\s+~end\s*/',$texto) as $bloque) { 
    if(preg_match_all('/(?:\~\d+\s+)\K.+?(?:\s+\S+)*?(?=\s+\~|$)/',$bloque,$sub_bloques)){ 
     $hola[]=$sub_bloques[0]; 
    } 
} 
var_export($hola); 

выход * переформатирован/конденсируется, чтобы сэкономить место на этой странице (View Demo):

array(
    array('11111111','222222222','3333333333'), 
    array('aaaaaaaaaaa','bbbbbbbbbb','cccccccccc','ddddddddddd'), 
    array('yyyyyyyyyyy 
xxxxxxxx 
ffffffffff','rrrrrrrrrrrr') 
) 

В качестве альтернативы, если вы хотите, чтобы все вложенные блоки, перечисленные в 1-мерной матрице (не разделенной блоками) выходная матрица может быть построена за один шаг:

if(preg_match_all("/(?:\~\d+\s*)\K.+?(?:\s+\S+)*?(?=\s+\~)/s", $texto, $coincidencias)){ 
    var_export($coincidencias[0]); 
} 

1-тусклый выход:

array (
    0 => '11111111', 
    1 => '222222222', 
    2 => '3333333333', 
    3 => 'aaaaaaaaaaa', 
    4 => 'bbbbbbbbbb', 
    5 => 'cccccccccc', 
    6 => 'ddddddddddd', 
    7 => 'yyyyyyyyyyy 
xxxxxxxx 
ffffffffff', 
    8 => 'rrrrrrrrrrrr', 
) 
+0

@VictorMoscosoLembcke Если мой ответ удовлетворяет, пожалуйста, присудите ему зеленый галочку (и, возможно, увеличьте его за то, что вы были полезны). Если что-то не совсем правильно, объясните мне, и я попытаюсь это исправить. – mickmackusa

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