Perl을 사용하여 두 파일을 라인별로 연결하는 방법은 몇 개입니까?

StackOverflow https://stackoverflow.com/questions/1636755

  •  06-07-2019
  •  | 
  •  

문제

File1이 다음과 같이 보인다고 가정합니다.

bye bye
hello
thank you

그리고 file2는 다음과 같습니다.

chao
hola
gracias

원하는 출력은 다음과 같습니다.

bye bye chao
hello hola
thank you gracias

나는이 문제를 해결하기 위해 이미 5 가지 접근 방식을 생각해 냈습니다. 그러나 나는 더 많은 방법, 아마도 더 간결하고 더 우아한 방법이 있어야한다고 생각하며, 더 멋진 것들을 더 배울 수 있기를 바랍니다 :)

다음은 이전 문제의 많은 솔루션에서 배운 내용을 바탕으로 지금까지 시도한 것입니다. 또한, 나는 Llama 책에서 얻은 지식을 소화하거나 내부화하려고 노력하고 있습니다.

코드 1 : 코드 1

#!perl
use autodie;
use warnings;
use strict;

open my $file1,'<','c:/file1.txt';
open my $file2,'<','c:/file2.txt';

while(defined(my $line1 = <$file1>)
        and defined(my $line2 = <$file2>)){
    die "Files are different sizes!\n" unless eof(file1) == eof(file2);
    $line1 .= $line2;
    $line1 =~ s/\n/ /;
    print "$line1 \n";
}

Code 2:

#!perl
use autodie;
use warnings;
use strict;

open my $file1,'<','c:/file1.txt';
my @file1 = <$file1>;

open my $file2,'<','c:/file2.txt';
my @file2 =<$file2>;

for (my $n=0; $n<=$#file1; $n++) {
    $file1[$n] .=$file2[$n];
    $file1[$n]=~s/\n/ /;
    print $file1[$n];
}

코드 3 :

#!perl
use autodie;
use warnings;
use strict;

open my $file1,'<','c:/file1.txt';
open my $file2,'<','c:/file2.txt';

my %hash;

while(defined(my $line1 = <$file1>)
      and defined(my $line2 = <$file2>)) {
  chomp $line1;
  chomp $line2;
  my ($key, $val) = ($line1,$line2);
  $hash{$key} = $val;
}
print map { "$_ $hash{$_}\n" } sort keys %hash;

Code 4:

#!perl
use autodie;
use warnings;
use strict;

open my $file1,'<','c:/file1.txt';
open my $file2,'<','c:/file2.txt';

while(defined(my $line1 = <$file1>)
      and defined(my $line2 = <$file2>)) {
  $line1 =~ s/(.+)/$1 $line2/;
  print $line1;
}

Code 5:

#!perl
use autodie;
use warnings;
use strict;

open my $file1,'<','c:/file1.txt';
my @file1 =<$file1>;

open my $file2,'<','c:/file2.txt';
my @file2 =<$file2>;

while ((@file1) && (@file2)){ 
    my $m = shift (@file1);
    chomp($m);

    my $n = shift (@file2);
    chomp($n);

    $m .=" ".$n;
    print "$m \n";
}

나는 다음과 같은 것을 시도했다 :

foreach $file1 (@file2) && foreach $file2 (@file2) {...}

그러나 Perl은 나에게 구문 오류 경고를 주었다. 나는 좌절했다. 그러나 우리는 둘을 달릴 수 있습니까? foreach 동시에 고리?

항상 의견, 제안 및 관대 한 코드 공유에 대해 항상 감사합니다 :)

도움이 되었습니까?

해결책

이것은 모든 파일에 대해 작동합니다.

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;

다른 팁

가장 우아한 방법은 포함되지 않습니다 perl 조금도:

paste -d' ' file1 file2

내가 골프 남자라면 다시 쓸 수 있었다 @FM의 답변 처럼:

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

당신은 하나의 라이너로 변할 수 있지만 그것은 단지 악입니다. ;-)

글쎄, 여기에는 100 자 미만이 있습니다.

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

비방해도 괜찮다면 (그리고 왜 도대체 그렇지 않은지 - 우리는 ~이다 다른 방법을 찾고), 나는 그 길을 광기를 발견했다고 생각합니다.

@_=@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

산출:

bye bye chao
hello hola
thank you gracias

당신의 더 쉬운 대안 코드 5 임의의 줄 수를 허용하고 파일이 다른 줄 (모자 팁 @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";
}

그리고 외부 모듈을 사용하지 않고 :

#!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";
}

두 파일 모두에 나타나는 줄만 연결하려면 다음과 같습니다.

#!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";
}

최소한의 오류 확인이있는 쉬운 것 :

#!/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";
}

그리고 아니요, 같은 스레드 내에서 두 개의 루프를 동시에 실행할 수 없습니다. fork, 그러나 그것은 동기식으로 실행되는 것이 보장되지 않을 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top