#!/usr/bin/perl # The Missing Textutils, Ondrej Bojar, obo@cuni.cz # http://www.cuni.cz/~obo/textutils # # Given any number of files as args, 'ziplines' produces a file where first # comes a line from the first file, then a line from the second, etc. # It produces blank lines if any of the files is shorter, so the output is # as long as the longest file. # # $Id: ziplines,v 1.9 2009-06-16 06:21:27 bojar Exp $ # use strict; use warnings; use IO::File; use Getopt::Long; my $diffonly = 0; # print only blocks with differing lines my $delim = 0; # add a blank line after each block my $blockdelimiter = undef; # what should be the delimiter of the blocks my $itemdelimiter = "\n"; # what should be the delimiter of items within each block my $namedelimiter = "\t"; # delimits filename and the line my $showname = 0; # show file name as the first column GetOptions( "diff-only" => \$diffonly, "delim" => \$delim, "block-delimiter=s" => \$blockdelimiter, "item-delimiter=s" => \$itemdelimiter, "name-delimiter=s" => \$namedelimiter, "showname" => \$showname, ) or exit 1; $itemdelimiter =~ s/\\n/\n/g; $itemdelimiter =~ s/\\t/\t/g; $itemdelimiter =~ s/\\\\/\\/g; die "Don't use --block-delimiter and --delim at the same time." if defined $blockdelimiter && $delim; $blockdelimiter = "\n\n" if $delim; $blockdelimiter = "\n" if !defined $blockdelimiter; $blockdelimiter =~ s/\\n/\n/g; $blockdelimiter =~ s/\\t/\t/g; $blockdelimiter =~ s/\\\\/\\/g; my @files = @ARGV; my @streams = map { my $openstr = ($_ =~ /\.gz$/ ? "zcat $_ |" : "< $_"); IO::File->new($openstr) or die "Can't open '$openstr'" } @files; while (1) { my $eofs = 0; my @block = (); my $all_same = 1; for(my $i=0; $i<=$#streams; $i++) { my $line; if (eof($streams[$i])) { $line = ""; } else { $line = readline($streams[$i]); chomp $line; } push @block, $line; $all_same = 0 if $diffonly && $block[-1] ne $block[0]; $eofs++ if eof($streams[$i]); } if (!$diffonly || !$all_same) { @block = map { $files[$_].$namedelimiter.$block[$_] } (0..$#block) if $showname; print join($itemdelimiter, @block); print $blockdelimiter; } last if $eofs == scalar @streams; }