중복된 라인 출력 문의 및 기타 질문 (perl 프로그래밍)

mamin79의 이미지

안녕하세요!

perl 프로그램 구성 중, 조언을 얻고자 글을 처음 써보네요~^^
설명이 너무 장황하였는데요, 조언 해 주시면 펄 공부하는데에 도움이 될 것 같습니다.~

(예제) test.txt 파일 (실제로 여러 파일들이 있고, 앞에 라인 숫자는 파일마다 상이합니다.)
1 / df16 3968
2 / 7218 acb7
3 / 8de7 5348
4 / 2f59 f418
5 / d0a6 0be7
6 / ec87 a4e8
7 / 1378 5b17
8 / c6d9 6271
9
10
11
12

위와 같이 이런 형태의 파일이 있습니다. 물론 라인 수는 엄청 길어서 제가 예제로 짤라서 넣은 샘플이구요.
현재는 n, n+1 라인만 비교해서 data 값들이 중복이 있는지 체크하는 것으로 짰습니다.
중복된 값이 없으면 --> OK, 중복된 값이 있으면 error

여기서 추가로 더 추가 하고 싶은게 있습니다.

1. 중복된 값이 있다면, 중복된 라인을 출력을 하는 것입니다.

2. 현재 n, n+1 라인만 비교하고 있는데, (1,2,3,4) 하고 (5,6,7,8) 비교, 4라인씩 비교를 하게끔 하는 것입니다. 그 다음 (5,6,7,8) 하고 (9,10,11,12) 하고 비교
그 중에서도 () () 내에서 하나라도 중복이 되면 error 가 되는 것입니다.
뒤에 라인수는 계속 있습니다.

#!/usr/bin/perl
use List::MoreUtils qw(uniq);
 
$filename = $ARGV[0] ;
@STR_code = ();
@unique_STR_code = ();
 
$linecnt = 0;
 
if (! open(READ_FILE, '<'.$filename))   { print "Can't read file : $filename\n"; die "Die! Can not open $filename\n"; 	}
 
while(<READ_FILE>) {
	($lineid,$code1,$code2) = ( $_ =~ m!(\d+)\s/\s(\S{4})\s(\S{4})!);			    
	$code = sprintf("%s_%s",$code1,$code2);  # 맨앞 4bit x 2  비교
	push( @STR_code,$code);
	$linecnt++;
	print ("$linecnt - $code\n");
}
close(READ_FILE);
 
@unique_STR_code = uniq @STR_code;
 
print ("비교한 쌍 수량: $#STR_code\n");
print ("중복 되지 않은 쌍 수량 : $#unique_STR_code\n");
 
$valance_cnt =  $#STR_code - $#unique_STR_code;
 
if ( $valance_cnt < 1 ) { print "Ok, 중복된 Key 가 없습니다."  
} else { print "Error! 중복된, $valance_cnt key 가 있습니다. "; }

raymundo의 이미지

N번째 그룹(네 줄짜리)과 N+1 번째 그룹만 비교하는 거죠? 1번 그룹과 3번 그룹은 비교하지 않고.

use strict;
use warnings;
 
my $filename = $ARGV[0];
my @prev_lines; # 직전에 읽은 그룹
my @this_lines; # 이번에 읽은 그룹
 
open my $fh, '<', $filename or die "can not open $filename: $!";
 
while ( @this_lines = read_chunk($fh, 4) ) {
    foreach my $prev ( @prev_lines ) {
        foreach my $this ( @this_lines ) {
            if ( $this->[1] eq $prev->[1]
                    and
                 $this->[2] eq $prev->[2] )
            {
                print "직전 그룹과 중복된 키 : $this->[0] - $this->[1]_$this->[2]\n";
            }
        }
    }
 
    @prev_lines = @this_lines;
}
 
close $fh;
 
 
# 파일을 한 번에 $mod 라인만큼 읽어서 반환
sub read_chunk {
    my ($fh,$mod) = @_;
 
    my @lines;
    while ( <$fh> ) {
        my ($lineid,$code1,$code2) = ( $_ =~ m!(\d+)\s/\s(\S{4})\s(\S{4})!);
        push @lines, [$lineid, $code1, $code2];
        return @lines unless $. % $mod;
    }
    return @lines;
}

좋은 하루 되세요!

mamin79의 이미지

역시 고수분들이 많이 있네요.

조언 감사 드립니다.
N번째 그룹(네 줄짜리)과 N+1 번째 그룹만 비교하는 거죠? 1번 그룹과 3번 그룹은 비교하지 않고.
--> 말씀하신 부분이 정확하게 맞습니다. !!^^

스크립트가 정확하게 작동하네요~~ 저도 스크립트 디테일하게 공부를 하도록 하겠습니다.

좋은 하루 되십시오.