Форум dkLab и Denwer
Здесь общаются Web-разработчики.
Генеральный спонсор:
Хостинг «Джино»

«Склеивание» файлов по горизонтали. (Ant)
Author Message
Ant
Сотрудник «Лаборатории»



Joined: 17 Jun 2003
Posts: 6837
Карма: 131
   поощрить/наказать


PostPosted: Mon Dec 22, 2003 1:13 am ()
   Post subject: «Склеивание» файлов по горизонтали.
Reply with quote

Данное решение «склеивает» n-е количество столбцов из разных фалов. Лояльно относится, если в каком-то столбце строк
больше/меньше. Только одно «но»: в ваших файлах не должен использоваться знак табуляции — это исказит содержимое выходного файла.

Синтаксис запуска: script.pl file1.txt file2.txt file3.txt и т.д.,
где file*.txt — файлы, которые необходимо «склеить».

Результатом работы является файл result.txt.
Code (perl): скопировать код в буфер обмена
#!path_to_perl

die (www.perldoc.com/perl5.6/pod/func/die.html) "You haven`t specify any files\n" unless @ARGV;
my ( $file, @argv ) = @ARGV;

open (www.perldoc.com/perl5.6/pod/func/open.html)( F, "$file" );
    @a = <F>;
close (www.perldoc.com/perl5.6/pod/func/close.html)( F );

while ( $file = shift (www.perldoc.com/perl5.6/pod/func/shift.html) @argv ) {
    my $sum_a = 0;
    my $sum_b = 0;     
    for ( $k = 0; $k <= $#a; ++$k ) {
        chomp (www.perldoc.com/perl5.6/pod/func/chomp.html)( $a[ $k ] );
        if ( length (www.perldoc.com/perl5.6/pod/func/length.html)( $a[ $k ] ) > $sum_a ) {
            $sum_a = length (www.perldoc.com/perl5.6/pod/func/length.html)( $a[ $k ] );
        }
    }
    open (www.perldoc.com/perl5.6/pod/func/open.html)( F, "$file" );
        @b = <F>;
    close (www.perldoc.com/perl5.6/pod/func/close.html)( F );
    for ( $k = 0; $k <= $#b; ++$k ) {
        chomp (www.perldoc.com/perl5.6/pod/func/chomp.html)( $b[ $k ] );
        if ( length (www.perldoc.com/perl5.6/pod/func/length.html)( $b[ $k ] ) > $sum_b ) {
            $sum_b = length (www.perldoc.com/perl5.6/pod/func/length.html)( $b[ $k ] );
        }
    }

    if ( $#a >= $#b ) {
        @wl = @a;
    } elsif ( $#a < $#b ) {
        @wl = @b;
    }

    for ( $i = 0; $i <= $#wl; ++$i ) {
        if ( length (www.perldoc.com/perl5.6/pod/func/length.html)( $a[ $i ] ) < $sum_a ) {
            $a[ $i ] .= " " x ( $sum_a - length (www.perldoc.com/perl5.6/pod/func/length.html)( $a[ $i ] ) );
        }
        if ( length (www.perldoc.com/perl5.6/pod/func/length.html)( $b[ $i ] ) < $sum_b ) {
            $b[ $i ] .= " " x ( $sum_b - length (www.perldoc.com/perl5.6/pod/func/length.html)( $b[ $i ] ) );
        }
        $a[ $i ] .= "    ".$b[ $i ];
        $a[ $i ] .= "\n" if ( $i < $#wl );
    }
}
open (www.perldoc.com/perl5.6/pod/func/open.html)( F, ">result.dat" );
    print (www.perldoc.com/perl5.6/pod/func/print.html) F @a;
close (www.perldoc.com/perl5.6/pod/func/close.html)( F );
Пример работы скрипта (только пример работы) находится в аттачменте.

Алгоритм решения:
Quote:
Читаем первый файл в массив. Запускаем самый главный цикл в программе, в котором поочерёдно будет обрабатываться каждый последующий файл.
В этом цикле, прежде всего, пускаем ещё однин и находим самую длинную строку в массиве @a. Это нужно для того, чтобы заполнить оператором «x» недостающие пробелы в строках.
Далее открываем следующий файл и проделываем тоже самое, что и с первым.
Далее главное узнать, какой массив больше. Дело в том, что если организовать while-цикл, как предлогал Максим, а другой файл (не тот, по которому проходит цикл) будет длинее, а, следовательно, значений в массиве у него будет больше, то картина полностью нарушится. ):
Так вот. Узнаём от чего мы будем отталкиваться в нашем цикле (правда это можно сделать намного элегантнее) и строим цикл.
В цикле как раз и заполняем строки недостающими пробелами, ставим разделитель столбцов в выходном файле (4 пробела) и переход строки (переход строки ставится только если мы не дошли до конца цикла).
Всё это дело присваивается массиву @a, то есть в следующем ходе цикла картина полностью повторится, как будто бы мы массив @a только что достали из файла (только в нём уже содержится 2 файла). И так далее.



result.zip
 Description:

Download
 Filename:  result.zip
 Filesize:  1.53 KB
 Downloaded:  986 Time(s)

Back to top
View user's profile Send private message Send e-mail
Ant
Сотрудник «Лаборатории»



Joined: 17 Jun 2003
Posts: 6837
Карма: 131
   поощрить/наказать


PostPosted: Mon Dec 22, 2003 1:18 am (спустя 5 минут)
   Post subject:
Reply with quote


М

Обсуждение этого решения в теме:
«Склеивание» файлов по горизонтали (обсуждение). (forum.dklab.ru/perl/heap/SkleivanieFaylovPoGorizontaliObsugdenie.html) .
Back to top
View user's profile Send private message Send e-mail
Egor Ermakov
Участник форума



Joined: 28 Jul 2003
Posts: 173
Карма: 6
   поощрить/наказать

Location: Откуда не возращаются

PostPosted: Mon Dec 22, 2003 10:51 pm (спустя 21 час 33 минуты)
   Post subject:
Reply with quote

Code (perl): скопировать код в буфер обмена
#!/usr/local/bin/perl -w
use strict;
my ($file,$num,$i,$curlength,$maxlength,$delim);
my (@result,@work);
die (www.perldoc.com/perl5.6/pod/func/die.html) "You haven`t specify any files\n" unless @ARGV;
$curlength=0;
#
$delim="    ";
#
while ($file=shift (www.perldoc.com/perl5.6/pod/func/shift.html)(@ARGV)){
                 $i=$maxlength=0;
                open (www.perldoc.com/perl5.6/pod/func/open.html)(FILE,"$file")or die (www.perldoc.com/perl5.6/pod/func/die.html) "Could`t open $file :$!";
#
#
#
#
#
#
#
#
                while(defined (www.perldoc.com/perl5.6/pod/func/defined.html)($work[$i]=<FILE>)){
                        chomp (www.perldoc.com/perl5.6/pod/func/chomp.html)($work[$i]);
                        if(!$result[$i]&&$curlength!=0){
                                $result[$i]=" " x ($curlength);
                        }
                        $work[$i]=~s (www.perldoc.com/perl5.6/pod/func/s.html)/\D+$//;
                        if (length (www.perldoc.com/perl5.6/pod/func/length.html)($work[$i])>$maxlength) {
                                $maxlength=length (www.perldoc.com/perl5.6/pod/func/length.html)($work[$i])
                        }
                        $i++;
                }
                $num=$i;
                close (www.perldoc.com/perl5.6/pod/func/close.html)(FILE);
#
#
#
#
#
        for($i=0;($i<$num or $i<scalar(@result));$i++){
                 if (defined (www.perldoc.com/perl5.6/pod/func/defined.html)($work[$i])) {
                        $result[$i].=$work[$i];
                                $result[$i].=" " x ($maxlength - length (www.perldoc.com/perl5.6/pod/func/length.html)($work[$i])).$delim;
                                }else{
                                $result[$i].=" " x($maxlength).$delim;
                }
                                undef (www.perldoc.com/perl5.6/pod/func/undef.html)($work[$i]);
        }
                $curlength=length (www.perldoc.com/perl5.6/pod/func/length.html)($result[0]);
}

#
#
open (www.perldoc.com/perl5.6/pod/func/open.html) (OUT,">result.out") or die (www.perldoc.com/perl5.6/pod/func/die.html) "Could`t open file to write:$!\n";
foreach(@result){
        s (www.perldoc.com/perl5.6/pod/func/s.html)/(\s (www.perldoc.com/perl5.6/pod/func/s.html)*$delim)*$//;
        print (www.perldoc.com/perl5.6/pod/func/print.html) OUT $_."\n";
}
close (www.perldoc.com/perl5.6/pod/func/close.html) (OUT);
Back to top
View user's profile Send private message
Enilatiar
Участник форума



Joined: 09 Jun 2003
Posts: 690
Карма: 24
   поощрить/наказать


PostPosted: Mon Jan 05, 2004 7:09 pm (спустя 13 дней 20 часов 17 минут)
   Post subject:
Reply with quote

Решение задачи, которое подразумевается в описании.
Code (perl): скопировать код в буфер обмена
my $tab = 0; #

#
my @Al;
foreach my $f ( @ARGV ) {
    open (www.perldoc.com/perl5.6/pod/func/open.html) F, $f;
    my $l = 0;
    while ( <F> ) {
        $l = length (www.perldoc.com/perl5.6/pod/func/length.html)($_)  if $l < length (www.perldoc.com/perl5.6/pod/func/length.html)($_);
    }
    push (www.perldoc.com/perl5.6/pod/func/push.html) @Al, $l+$tab;
    close (www.perldoc.com/perl5.6/pod/func/close.html) F;
}

#
use Symbol;
my @F = map (www.perldoc.com/perl5.6/pod/func/map.html) { open (www.perldoc.com/perl5.6/pod/func/open.html) my $f=gensym, $_; $f } @ARGV;

while (1) {
    #
    my @a = ();   
    foreach (@F) {
        my $s = (eof (www.perldoc.com/perl5.6/pod/func/eof.html) $_)? '' : scalar (www.perldoc.com/perl5.6/pod/func/scalar.html) <$_>;
        chomp (www.perldoc.com/perl5.6/pod/func/chomp.html) $s;
        push (www.perldoc.com/perl5.6/pod/func/push.html) @a, $s;
    }

    #
    last  unless  (join (www.perldoc.com/perl5.6/pod/func/join.html) '', @a);

    foreach my $i (0..$#a) {
        printf (www.perldoc.com/perl5.6/pod/func/printf.html) '%-*s', $Al[$i], $a[$i];
    }
    print (www.perldoc.com/perl5.6/pod/func/print.html) "\n";
}

#
close (www.perldoc.com/perl5.6/pod/func/close.html) $_ foreach @F;
Рекомендуемое мной решение подобных задач:
Code (perl): скопировать код в буфер обмена
#
#
#
# 4 5 6 7
# 4 5 6
# 4 5 6
#   5 6
#   5 6
#     6

my $tab = "\t";

use Symbol;
my @F = map (www.perldoc.com/perl5.6/pod/func/map.html) { open (www.perldoc.com/perl5.6/pod/func/open.html) my $f=gensym, $_; $f } @ARGV;

while (1) {
    my @a = (); #
    foreach (@F) {
        my $s = (eof (www.perldoc.com/perl5.6/pod/func/eof.html) $_)? '' : scalar (www.perldoc.com/perl5.6/pod/func/scalar.html) <$_>;
        chomp (www.perldoc.com/perl5.6/pod/func/chomp.html) $s;
        push (www.perldoc.com/perl5.6/pod/func/push.html) @a, $s;
    }
    #
    last  unless  (join (www.perldoc.com/perl5.6/pod/func/join.html) '', @a);
    #
    print (www.perldoc.com/perl5.6/pod/func/print.html) join (www.perldoc.com/perl5.6/pod/func/join.html) ($tab, @a), "\n";
}
close (www.perldoc.com/perl5.6/pod/func/close.html) $_  foreach @F;
Code (perl): скопировать код в буфер обмена
# Простая склейка файлов
# 4 5 6 7
# 4 5 6
# 4 5 6
# 5 6
# 5 6
# 6

use Symbol;
my @F = map (www.perldoc.com/perl5.6/pod/func/map.html) { open (www.perldoc.com/perl5.6/pod/func/open.html) my $f=gensym, $_; $f } @ARGV;

push (www.perldoc.com/perl5.6/pod/func/push.html) @F, 1;
while ($_ = shift (www.perldoc.com/perl5.6/pod/func/shift.html) @F) {
    if ( $_ == 1 ) {
        last  unless @F;
        print (www.perldoc.com/perl5.6/pod/func/print.html) "\n";
    } elsif ( eof (www.perldoc.com/perl5.6/pod/func/eof.html) $_ ) {
        close (www.perldoc.com/perl5.6/pod/func/close.html) $_;
        next;
    } else {
        chomp (www.perldoc.com/perl5.6/pod/func/chomp.html)( my $s = scalar (www.perldoc.com/perl5.6/pod/func/scalar.html) <$_> );
        print (www.perldoc.com/perl5.6/pod/func/print.html) "$s ";
    }
    push (www.perldoc.com/perl5.6/pod/func/push.html) @F, $_;
}
close (www.perldoc.com/perl5.6/pod/func/close.html) $_  foreach @F;
Back to top
View user's profile Send private message
иван бахчеев
Заглянувший



Joined: 21 Dec 2003
Posts: 13
Карма: 0
   поощрить/наказать


PostPosted: Sat Jan 24, 2004 1:08 pm (спустя 18 дней 17 часов 58 минут)
   Post subject: по-моему вы извращенец
Reply with quote

очень рекомендую почитать man join, man sort, а если вы меня отошлете к использованию ОС, отличной от linux, то рекомендую вам ознакомиться с пакетом UnixUtils. применение скрипта, написанного на перл и работающего в командной строке, считаю нецелесообразным потому как есть специальные для этого программы, менее функционально ограниченные и поддерживаемые, наконец.
Back to top
View user's profile Send private message
Ant
Сотрудник «Лаборатории»



Joined: 17 Jun 2003
Posts: 6837
Карма: 131
   поощрить/наказать


PostPosted: Sat Jan 24, 2004 3:48 pm (спустя 2 часа 39 минут)
   Post subject:
Reply with quote


!

иван бахчеев wrote:
если вы меня отошлете к использованию
Скорее я отошлю Вас вот в эту тему: «Склеивание» файлов по горизонтали (обсуждение). (forum.dklab.ru/perl/heap/SkleivanieFaylovPoGorizontaliObsugdenie.html) .
И ещё вот в эту: Правила этого раздела. (forum.dklab.ru/perl/advises/PravilaEtogoRazdela.html) .
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   Reply to topic All times are GMT + 3 Hours
Page 1 of 1    Email to a Friend.
You cannot post new topics in this forum. You cannot reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.
XML