помогите с preg_match_all и созданием значений по умолчанию

Мне нужна помощь/экспертиза php для настройки/изменения этой функции preg_match_all. Что я хочу сделать, так это создать значения по умолчанию для отсутствующих упорядоченных пар. Он правильно сопоставляет данные, но мне нужна логика, чтобы добавить некоторые значения по умолчанию. (см. ОЖИДАНИЕ вывода данных ниже). Можно ли это обработать в рамках этой же функции? Спасибо!

Фрагмент preg_match_all:

foreach ($InputFile as $line){
    preg_match_all("/([0-9])-([^=]+)=([^;]+);/", $line, $matches, PREG_SET_ORDER);
    $LineData = array();
    foreach ($matches as $information)
        $LineData[$information[2]] = $information[3];
    $data[] = $LineData;
print_r($LineData);
}

Файл данных имеет максимум (8) атрибутов в следующем порядке:

1-Server
2-Logdate
3-BackupSet
4-StartTime
5-Duration
6-DBServer
7-Size
8-Status

Но в файле есть экземпляры, где есть строки, которые НЕ имеют всех атрибутов, таких как 5-Duration, 7-Size, 8-Status. Я хочу установить значение по умолчанию для этих атрибутов, например:

5-Duration => 0
7-Size     => 0
8-Status   => incomplete

Выход массива: (текущий)

Array ( [Server] => hostname3.prop.abc
        [Logdate] => Wed Jan 05 2011
        [BackupSet] => rfoo101.az1
        [StartTime] => 20110105000004
        [Duration] => 00:56:47
        [DBServer] => rfoo101.prop.az1.kaz.com 
        [Size] => 56.51
        [Status] => Backup succeeded )
Array ( [Server] => hostname3.prop.abc
        [Logdate] => Wed Jan 05 2011
        [BackupSet] => bar202.az4_lvm
        [StartTime] => 20110105040003
        [DBServer] => bar202.prop.az4.kaz.com) 
Array ( [Server] => hostname10.prop.az2
        [Logdate] => Thu Jan 06 2011
        [BackupSet] => bar201_az2_lvm
        [StartTime] => 20110106151622
        [DBServer] => bar201.prop.az2.kaz.com  
        [Status] => Backup failed )

Ожидается вывод данных: (СО ЗНАЧЕНИЯМИ ПО УМОЛЧАНИЮ)

Array ( [Server] => hostname3.prop.abc
        [Logdate] => Wed Jan 05 2011
        [BackupSet] => rfoo101.az1
        [StartTime] => 20110105000004
        [Duration] => 00:56:47
        [DBServer] => rfoo101.prop.az1.kaz.com 
        [Size] => 56.51
        [Status] => Backup succeeded )
Array ( [Server] => hostname3.prop.abc
        [Logdate] => Wed Jan 05 2011
        [BackupSet] => bar202.az4_lvm
        [StartTime] => 20110105040003
        [Duration] => 0 
        [DBServer] => bar202.prop.az4.kaz.com 
        [Size]     => 0  
        [Status]   => incomplete) 
Array ( [Server] => hostname10.prop.az2
        [Logdate] => Thu Jan 06 2011
        [BackupSet] => bar201_az2_lvm
        [StartTime] => 20110106151622
        [Duration]  => 0
        [DBServer] => bar201.prop.az2.kaz.com 
        [Size]   => 0 
        [Status] => Backup failed )

Изменения кода в помощь:

<?php
$defaults = array(
    'Duration' => 0,
    'Size'     => 0,
    'Status'   => 'incomplete' );

$data = array();
$InputFile = file("test.txt");

foreach ($InputFile as $line){
    preg_match_all("/([0-9])-([^=]+)=([^;]+);/", $line, $matches, PREG_SET_ORDER); 
    $LineData = array();
    foreach ($matches as $information)                  
        $LineData[$information[2]] = $information[3];  
    $data[] = array_merge($defaults, $LineData);
}

print_r($data);
?>

person cjd143SD    schedule 11.01.2011    source источник


Ответы (2)


Вы можете создать массив значений по умолчанию, а затем использовать array_merge() для создания выходной массив со значениями по умолчанию, за исключением случаев, когда они переопределены значениями из проанализированного совпадения:

$defaults = array(
    'Duration' => 0,
    'Size' => 0,
    'Status' => 'incomplete' );

$output_with_defaults = array_merge($defaults, $output_without_defaults);

Это работает из-за следующего поведения от array_merge():

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

В вашем случае вы хотите изменить эту строку:

$data[] = $LineData;

to be...

$data[] = array_merge($defaults, $LineData);

(И объявите массив значений по умолчанию перед началом любого текущего кода — он не должен находиться внутри каких-либо циклов.)

person Amber    schedule 11.01.2011
comment
Довольно интересно. Могу ли я подключить это после функции preg_match_all в foreach? Спасибо. - person cjd143SD; 11.01.2011
comment
Я отредактировал более подробное объяснение для вашего конкретного случая. - person Amber; 11.01.2011
comment
Привет, янтарь, я разместил свой код сверху с вашим вкладом. Я еще не могу заставить слияние работать. что-то не в порядке. спасибо - person cjd143SD; 11.01.2011
comment
Я отредактировал код, который вы разместили. Обратите внимание, что он действительно работал (кроме ненужной репликации моего примера вызова array_merge), но ваш оператор печати печатал неизмененную версию массива. Я изменил его, чтобы впоследствии использовать print_r() вызов $data, который покажет измененную версию. - person Amber; 11.01.2011

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

if (!is_array($LineData))
{
  $LineData = 
  array(
    'Server'    => ...,
    'Logdate'   => ...,
    'BackupSet' => ...,
    'StartTime' => ...,
    'Duration'  => 0,
    'DBServer'  => ...,
    'Size'      => 0,
    'Status'    => 'incomplete',
  );
}
foreach ($matches as $information)
{
  $LineData[$information[2]] = $information[3];
}
$data[] = $LineData;
person ajreal    schedule 11.01.2011
comment
будет ли это после функции preg_match_all? - person cjd143SD; 11.01.2011
comment
@ cjd143SD - Прежде чем вы инициируете $ LineData. Это просто для того, чтобы все совпадения начинались с массива с некоторым значением по умолчанию. Итак, если какая-то информация недоступна, будет использоваться значение по умолчанию, не сильно отличающееся от вопроса @Amber. - person ajreal; 11.01.2011