Обработанные экспериментельные данные часто представляют собой ряды чисел, по которым затем небходимо строить графики. Иногда требуется склеить данные из двух источников так, чтобы новые данные были дополнительными столбцами в уже существующих данных.
Задача:
Есть данные 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.
Вертикальная конкатенация двух файлов
Подписаться на:
Комментарии к сообщению (Atom)
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
2 Анонимный пишет...
man paste?
Ага, похоже на то. А я apropos-ом искал и что-то не нашёл. Век живи, век учись...
2 Анонимный пишет...
хм.. как не прискорбно, но предыдущий оратор был прав..
Так я затем и спросил - может, кто знает решение лучше. Я исторически прикипел к перлу :-)
вот ваше решение:
$ paste -d " " RAWMAXmeasurementresult shutter > ourendresult
Золотые вы мои анонимные комментаторы! Чтоб я без вас делал!? Вот это круто, вот это юникс-вей... добавил в пост и добавил в скрипт :-)
Ещё раз спасибо!
Очень напоминает задачки по информатике в Институте управления на 2 курсе.
Тока там надо было строго на баше.
Да, coreutils вообще очень полезная вещь. Не только paste. join тоже неплохая вещь.
Думаю, замечание про paste лучше вынести в начало поста.
2 Artem пишет...
Очень напоминает задачки по информатике в Институте управления на 2 курсе.
Да, только мне её надо было решать быстро и поздно вечером, так как данные нужны были утром. Тут уж не до красивых решений :-)
2 jetxee пишет...
Да, coreutils вообще очень полезная вещь. Не только paste. join тоже неплохая вещь.
Так я ж говорю: не знал про paste и начал изобретать перловый велосипед.
Думаю, замечание про paste лучше вынести в начало поста.
Разумно, пост поправлен.
Ещё раз спасибо!
Эм. Пока ещё сидел под вендой, писал что-то похожее на перле. Только это было намного короче, строчек 10 всего. Это не пальцегнутие, а к тому, что помойму такие утилитки проще писать на перле/шелле, т.к. тексты совсем разные бывают, с кучей мусора или неровными пробелами.
В тему поста: Для похожих целей требовалось транспонировать файл перед обработкой (данные в строках, а не столбцах). Для сего напсал гомоздкую структуру на шеле (приведу ниже). Может кто знает решение красивше и проще?
Структура:
#!/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
Отправить комментарий