How many different ways are there to concatenate two files line by line using Perl?

前端 未结 5 2043
鱼传尺愫
鱼传尺愫 2020-12-15 13:59

Suppose file1 looks like this:

bye bye
hello
thank you

And file2 looks like this:

chao
hola
gracias

The desired output is this:

相关标签:
5条回答
  • 2020-12-15 14:19

    If I were a golfing man, I could rewrite @FM's answer as:

    ($,,$\)=(' ',"\n");@_=@ARGV;open $_,$_ for @_;print
    map{chomp($a=<$_>);$a} @_=grep{!eof $_} @_ while @_
    

    which you might be able to turn into a one-liner but that is just evil. ;-)

    Well, here it is, under 100 characters:

    C:\Temp> perl -le "$,=' ';@_=@ARGV;open $_,$_ for @_;print map{chomp($a =<$_>);$a} @_=grep{!eof $_ }@_ while @_" file1 file2

    If it is OK to slurp (and why the heck not — we are looking for different ways), I think I have discovered the path the insanity:

    @_=@ARGV;chomp($x[$.-1]{$ARGV}=$_) && eof
    and $.=0 while<>;print "@$_{@_}\n" for @x
    

    C:\Temp> perl -e "@_=@ARGV;chomp($x[$.-1]{$ARGV}=$_) && eof and $.=0 while<>;print qq{@$_{@_}\n} for @x" file1 file2

    Output:

    bye bye chao
    hello hola
    thank you gracias
    
    0 讨论(0)
  • 2020-12-15 14:21

    An easier alternative to your Code 5 which allows for an arbitrary number of lines and does not care if files have different numbers of lines (hat tip @FM):

    #!/usr/bin/perl
    
    use strict; use warnings;
    
    use File::Slurp;
    use List::AllUtils qw( each_arrayref );
    
    my @lines = map [ read_file $_ ], @ARGV;
    
    my $it = each_arrayref @lines;
    
    while ( my @lines = grep { defined and chomp and length } $it->() ) {
        print join(' ', @lines), "\n";
    }
    

    And, without using any external modules:

    #!perl
    use autodie; use warnings; use strict;
    
    my ($file1, $file2) = @ARGV;
    
    open my $file1_h,'<', $file1;
    my @file1 = grep { chomp; length } <$file1_h>;
    
    open my $file2_h,'<', $file2;
    my @file2 =  grep { chomp; length } <$file2_h>;
    
    my $n_lines = @file1 > @file2 ? @file1 : @file2;
    
    for my $i (0 .. $n_lines - 1) {
        my ($line1, $line2) = map {
            defined $_ ? $_ : ''
        } $file1[$i], $file2[$i];
        print $line1, ' ', $line2, "\n";
    }
    

    If you want to concatenate only the lines that appear in both files:

    #!perl
    use autodie; use warnings; use strict;
    
    my ($file1, $file2) = @ARGV;
    
    open my $file1_h,'<', $file1;
    my @file1 = grep { chomp; length } <$file1_h>;
    
    open my $file2_h,'<', $file2;
    my @file2 =  grep { chomp; length } <$file2_h>;
    
    my $n_lines = @file1 < @file2 ? @file1 : @file2;
    
    for my $i (0 .. $n_lines - 1) {
        print $file1[$i], ' ', $file2[$i], "\n";
    }
    
    0 讨论(0)
  • 2020-12-15 14:32

    An easy one with minimal error checking:

    #!/usr/bin/perl -w
    
    use strict;
    
    open FILE1, '<file1.txt';
    open FILE2, '<file2.txt';
    
    while (defined(my $one = <FILE1>) or defined(my $twotemp = <FILE2>)){
        my $two = $twotemp ? $twotemp : <FILE2>;
        chomp $one if ($one);
        chomp $two if ($two);
        print ''.($one ? "$one " : '').($two ? $two : '')."\n";
    }
    

    And no, you can't run two loops simultaneous within the same thread, you'd have to fork, but that would not be guaranteed to run synchronously.

    0 讨论(0)
  • 2020-12-15 14:35

    This works for any number of files:

    use strict;
    use warnings;
    use autodie;
    
    my @handles = map { open my $h, '<', $_; $h } @ARGV;
    
    while (@handles){
        @handles = grep { ! eof $_ } @handles;
        my @lines = map { my $v = <$_>; chomp $v; $v } @handles;
        print join(' ', @lines), "\n";
    }
    
    close $_ for @handles;
    
    0 讨论(0)
  • 2020-12-15 14:42

    The most elegant way doesn't involve perl at all:

    paste -d' ' file1 file2
    
    0 讨论(0)
提交回复
热议问题