Вертикальная конкатенация двух файлов

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

Задача:
Есть данные A:

$ cat RAWMAXmeasurementresult
2.7100000e+02 2.8300000e+02 2.8000000e+02
2.7300000e+02 2.8700000e+02 2.8400000e+02
2.7400000e+02 2.9600000e+02 2.9000000e+02
2.7800000e+02 3.0400000e+02 2.9800000e+02

Есть другой файл с данными B, полученный обработкой результата эксперимента в другой программе:
$ cat shutter
.00024414062500000000
.00031661600810536980
.00037652020030874656
.00048828125000000000

Нужно сделать так, чтобы в результате получился файл типа:
2.7100000e+02 2.8300000e+02 2.8000000e+02 .00024414062500000000
2.7300000e+02 2.8700000e+02 2.8400000e+02 .00031661600810536980
2.7400000e+02 2.9600000e+02 2.9000000e+02 .00037652020030874656
2.7800000e+02 3.0400000e+02 2.9800000e+02 .00048828125000000000
Так проще строить графики в гнуплоте, что в скриптах реализуется сравнительно просто.

Условия:
1. Ряды A и B можно перемещать, но нежелательно менять местами данные в ряде А.
2. Решение должно предполагать автоматизированную обработку (данных очень много, Ексель \ ОпенОфис Calc отпадают).
3. Ряд B получается не напрямую, сделать всё в одной программе нельзя.
4. Разделители - пробелы (количество неважно).
5. Задача не надуманная.

Что требуется:
Скрипт\программа, делающая такую конкатенацию, максимально кроссплатформенная (никаких вижуал васиков), ориентированная на *nix-среду.


Решение:
Изумительное по краткости и лаконичности: использование команды paste.
$ paste -d " " RAWMAXmeasurementresult shutter > ourendresult
И вся любовь.

Первоначально найденное решение:
Скрипт на Perl делающий всё это:

#! /usr/bin/perl
use strict;
use warnings;

my $kmvSourceFileName="RAWMAXmeasurementresult"; ## File that will be expanded by adding data
my $kmvTargetFileName="shutter";## File to be added to source file

my @kmvSourceFile =`cat $kmvSourceFileName`; ## file content
my @kmvTargetFile =`cat $kmvTargetFileName`;

my $kmvMaxIndexSourceFile = scalar @kmvSourceFile; ## how many elements in massive?

for (my $ii=0; $ii<$kmvMaxIndexSourceFile; $ii++)
{
if (index($kmvSourceFile[$ii], "\n")>0) ## if there is end-of-line symbol - remove it from source line
{
chop $kmvSourceFile[$ii];
}
$kmvSourceFile[$ii] = $kmvSourceFile[$ii]." ".$kmvTargetFile[$ii];
}

my $kmvResultFileName = $kmvSourceFileName.$kmvTargetFileName;

open(DATA, "+>$kmvResultFileName");##Открываем файл, куда пишем тестовые результаты
print (DATA @kmvSourceFile); ## Сюда пишем тестовые результаты
close(DATA); ##Закрываем файл, куда пишем тестовые результаты

Скрипт есть и он работает, но з
олотые мои анонимные комментаторы предложили решение, изумительное по краткости и лаконичности: использование команды paste.

9 комментариев: |высказаться!| RSS-лента дискуссии.|
Анонимный комментирует...

#!/usr/bin/perl
use strict;
use warnings;

# file with 3 columns
my $file1 = "/tmp/file1";
# file with 1 column
my $file2 = "/tmp/file2";
# target
my $result = "/tmp/result";

open(F1,$file1) or die $!;
open(F2,$file2) or die $!;
open(FT,'>',$result) or die $!;
while(my $tmp1 = < F1 > ){
chop($tmp1); print FT "$tmp1 ";
my $tmp2 = "< F2 >";
print FT $tmp2;
}
# это при условии что файлы
# с одинаковым кол-вом строк

Анонимный комментирует...

man paste?

Анонимный комментирует...

хм.. как не прискорбно, но предыдущий оратор был прав..
вот ваше решение:
$ paste -d " " RAWMAXmeasurementresult shutter > ourendresult

virens комментирует...

2 Анонимный пишет...
man paste?
Ага, похоже на то. А я apropos-ом искал и что-то не нашёл. Век живи, век учись...

2 Анонимный пишет...
хм.. как не прискорбно, но предыдущий оратор был прав..
Так я затем и спросил - может, кто знает решение лучше. Я исторически прикипел к перлу :-)

вот ваше решение:
$ paste -d " " RAWMAXmeasurementresult shutter > ourendresult

Золотые вы мои анонимные комментаторы! Чтоб я без вас делал!? Вот это круто, вот это юникс-вей... добавил в пост и добавил в скрипт :-)
Ещё раз спасибо!

Past комментирует...

Очень напоминает задачки по информатике в Институте управления на 2 курсе.
Тока там надо было строго на баше.

jetxee комментирует...

Да, coreutils вообще очень полезная вещь. Не только paste. join тоже неплохая вещь.

Думаю, замечание про paste лучше вынести в начало поста.

virens комментирует...

2 Artem пишет...
Очень напоминает задачки по информатике в Институте управления на 2 курсе.
Да, только мне её надо было решать быстро и поздно вечером, так как данные нужны были утром. Тут уж не до красивых решений :-)

2 jetxee пишет...
Да, coreutils вообще очень полезная вещь. Не только paste. join тоже неплохая вещь.
Так я ж говорю: не знал про paste и начал изобретать перловый велосипед.

Думаю, замечание про paste лучше вынести в начало поста.
Разумно, пост поправлен.

Ещё раз спасибо!

divan комментирует...

Эм. Пока ещё сидел под вендой, писал что-то похожее на перле. Только это было намного короче, строчек 10 всего. Это не пальцегнутие, а к тому, что помойму такие утилитки проще писать на перле/шелле, т.к. тексты совсем разные бывают, с кучей мусора или неровными пробелами.

zar комментирует...

В тему поста: Для похожих целей требовалось транспонировать файл перед обработкой (данные в строках, а не столбцах). Для сего напсал гомоздкую структуру на шеле (приведу ниже). Может кто знает решение красивше и проще?
Структура:

#!/bin/sh
file1=$1
file2=$2
tmpfile=file`date +%s`
tmpfile2=file2`date +%s`

rm -f $file2;
rm -f $tmpfile;
rm -f $tmpfile2;
touch $file2;
cat $file1|\
while read line; do
touch $tmpfile
for word in $line; do
echo $word >> $tmpfile;
done
paste -d " " $file2 $tmpfile > $tmpfile2 ;
cat $tmpfile2 > $file2;
rm -f $tmpfile;
rm -f $tmpfile2;
done

Отправить комментарий

Подписаться на RSS-ленту комментариев к этому посту.