shell — объединяет 2 текстовых файла на основе первого столбца, используя переполнение стека

У меня есть 2 файла журнала с несколькими строками, как

первый:

1|2016-04-13|...
3|2016-03-13|...

второй:

2|POST|accept: txt|...
3|POST|accept: txt|...

Ожидаемый результат:

3|2016-03-13|...|POST|accept: txt|...

Поэтому мне нужно объединить все данные в один файл на основе первого столбца (ID) с помощью сценариев PHP.

Заметка: количество строк может быть разным. Требуется только пересечение (с учетом порядка)

1

Решение

откройте оба файла журнала.

вы можете использовать fopen и fgets (в цикле foreach / while), чтобы получить строки в массив

или с помощью file_get_contents взорвать файл с помощью \ n (\ r \ n в Win)

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

 $log1Lines = array("3|...|...", "4|...|...");
$log2Lines = array("2|...|...", "3|...|...");

$merged = array();

foreach($log1Lines as $row1){
$id1 = explode("|", $row1)[0];
foreach($log2Lines as $row2){
$exploded = explode("|", $row2);
$id2 = array_shift($exploded);
if($id1 == $id2){
$merged[$id1] = $row1 . "|" . implode("|", $exploded);
}
}
}
print_r($merged);

Теоретически это должно быть выполнимо без циклов (сравнение разобранных индексов между двумя массивами с помощью array_intersect), но у меня нет решения сделать это прямо сейчас.

надеюсь, это поможет немного.

1

Другие решения

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

<?php
class Merger
{
protected $separator = '|';
protected $data = [];
protected $initialised = false;

public function mergeFile($filename)
{
$file = new SplFileObject($filename);
$fileKeys = [];

// Read the information out of the current file
while (!$file->eof()) {
$line = $file->fgets();
$parts = explode($this->separator, trim($line));
$id = array_shift($parts);
$fileKeys[] = $id;

$fileData[$id] = $parts;
}

// First pass: add everything
if (!$this->initialised)
{
$this->data = $fileData;
}

// Subsequent passes, only add things that have already been seen, then
// clear out anything that wasn't in the current file
else
{
foreach ($fileData as $id => $data)
{
if ($this->data[$id])
{
$this->data[$id] = array_merge($this->data[$id], $data);
}
}

$this->data = array_filter($this->data, function ($e) use ($fileKeys) {
return in_array($e, $fileKeys);
}, ARRAY_FILTER_USE_KEY);
}

$this->initialised = true;
}

public function output($filename)
{
foreach ($this->data as $id => $data)
{
$output .= $id . $this->separator . implode($this->separator, $data) . PHP_EOL;
}

file_put_contents($filename, $output);
}
}

$merger = new Merger;
$merger->mergeFile('1.txt');
$merger->mergeFile('2.txt');

echo $merger->output('output.txt');
1

Мое решение:

<?php
exec ("awk -F'|' -vOFS='|' '(NR==FNR){a[$1]=$0; next}{if(a[$1]){print $2,a[$1]}}' first.log second.log > result.log");
?>

я использовал Exec PHP-функция для запуска сценария оболочки

awk -F'|' -vOFS='|' '(NR==FNR){a[$1]=$0; next}{if(a[$1]){print $2,a[$1]}}' first.log second.log > result.log

Вот -F'|' указывает ‘|’ символ как разделитель, first.log а также second.log мои файлы для слияния.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector