![각 행 쌍의 정보를 하나의 행으로 결합하려면 어떻게 해야 합니까?](https://linux55.com/image/91871/%EA%B0%81%20%ED%96%89%20%EC%8C%8D%EC%9D%98%20%EC%A0%95%EB%B3%B4%EB%A5%BC%20%ED%95%98%EB%82%98%EC%9D%98%20%ED%96%89%EC%9C%BC%EB%A1%9C%20%EA%B2%B0%ED%95%A9%ED%95%98%EB%A0%A4%EB%A9%B4%20%EC%96%B4%EB%96%BB%EA%B2%8C%20%ED%95%B4%EC%95%BC%20%ED%95%A9%EB%8B%88%EA%B9%8C%3F.png)
다음과 같은 데이터가 있습니다(실제 데이터에는 50,000자릿수와 8000행이 넘습니다).
입력하다:
1 11122
1 21121
2 22221
2 11122
3 21121
3 11122
동일한 이름을 가진 첫 번째 행의 값 옆에 두 번째 행의 값을 배치하고 싶습니다. 또한 각 값 쌍 사이의 구분 기호로 두 개의 공백이 있어야 하고, 서로 다른 값 쌍 사이의 구분 기호로 탭이 있어야 합니다. 출력은 다음과 같아야 합니다.
산출:
1 1 2 1 1 1 1 2 2 2 1
2 2 1 2 1 2 1 2 2 1 2
3 2 1 1 1 1 1 2 2 1 2
어떤 제안이 있으십니까?
답변1
나는 Perl을 사용하고 다음과 같이 oneliner로 실행합니다.
perl -wne 'sub parseline { ($id,$v) = split; return split //,$v };
@a = parseline();
print "$id\t";
$_ = <>;
@b = parseline();
for ($i=0; $i<@a; $i++) {
print "$a[$i] $b[$i]\t"
};
print "\n"' < input > output
설명하다:
perl -wne
각 입력 줄에 대해 나머지 명령을 실행합니다.sub parseline { .... }
입력을 구문 분석하고 줄의 첫 번째 숫자를 설정$id
하고 나머지는 문자 배열로 반환합니다.@a=parseline()
문자의 첫 번째 행은 @a 배열에 저장됩니다.- 다음으로 인쇄
$id
하고 TAB(\t
) 을 누릅니다. $_=<>; @b=parseline();
다음 (짝수) 행을 읽고 해당 데이터를 배열에 넣습니다.@b
for ($i=0; $i<@a; $i++) { print "$a[$i] $b[$i]\t" }
배열의 각 요소에 대해@a
요소, 두 개의 공백, 배열의 해당 요소를 인쇄한@b
다음 탭을 인쇄합니다.print "\n"
끝에 개행 문자를 인쇄합니다- at start 매개변수로 인해
-n
전체 프로세스는 3행, 5행, 7행 순으로 시작됩니다.perl
< input > output
입력을 읽는 파일과 출력을 쓰는 파일을 나타냅니다.
참고: 코드는 각 줄 끝에 추가 탭을 인쇄합니다. 크라우드소싱을 방지하고 코드를 좀 더 단순하게 유지하기 위한 독자의 연습으로 이를 제거했습니다. 또한 코드에서는 쌍을 이루는 행이 항상 두 개의 행이 차례로 연속되는 것으로 가정합니다(예제 참조).
입력 파일을 한 줄씩 처리하므로 수천 줄에 걸쳐 쉽게 선형적으로 확장할 수 있습니다.
답변2
pairwise
이는 모듈 의 함수를 사용하여 List:MoreUtils
두 배열을 연결하고 ID가 일치하는 행(첫 번째 필드)이 연속 행에 있을 필요가 없는 Matija Nalis의 스크립트 버전입니다 . 즉, 여러 줄로 구분할 수 있습니다.
#! /usr/bin/perl
use strict;
use warnings;
use List::MoreUtils qw(pairwise);
sub parseline { my ($id,$v) = split; return $id, split //,$v };
my %ID=();
while (<>) {
my ($id, @line) = parseline();
if ( !defined($ID{$id}) ) {
push @{ $ID{$id} }, @line ;
} else {
my @paired = pairwise { "$a $b" } @{ $ID{$id} }, @line;
print join("\t", $id, @paired), "\n";
delete $ID{$id};
};
};
$id
MN의 parseline
서브루틴은 전역 변수를 사용하는 대신 각 행의 ID 및 요소 배열을 반환하도록 수정되었습니다.
$id
%ID
구문 분석된 각 행의 해시를 저장하기 위한 키로 사용됩니다. 주어진 을 처음 볼 때 구문 분석된 행 배열( )을 해시에 $id
저장 하고 다음 행으로 이동합니다. @line
다음에 이를 볼 때 저장된 배열을 현재 @line
배열과 쌍으로 연결하고 TAB 필드 구분 기호를 사용하여 인쇄한 다음 해시 $id
에서 %ID
제거합니다 .
man List::MoreUtils
이 기능의 작동 방식에 대한 pairwise
자세한 내용은 리소스를 참조하세요 . 그런데 List::Util
및 는 List::MoreUtils
다양한 목록(배열이라고도 함) 작업을 수행하기 위한 두 가지 훌륭한 모듈입니다.
산출:
$ ./zara.pl zara.txt
1 1 2 1 1 1 1 2 2 2 1
2 2 1 2 1 2 1 2 2 1 2
3 2 1 1 1 1 1 2 2 1 2