2012-09-20 4 views
0

다음과 같은 입력 파일이 있습니다. 열 2,3,을 기반으로 여러 파일로 나누어야합니다. 파일에 더 많은 열이 있지만 잘라 내기 명령을 사용하여 필요한 열만 가져 왔습니다.대용량 파일을 열 연결을 기반으로 작은 여러 파일로 분할

12,Accounts,India,free,Internal 
13,Finance,China,used,Internal 
16,Finance,China,free,Internal 
12,HR,India,free,External 
19,HR,China,used,Internal 
33,Finance,Japan,free,Internal 
39,Accounts,US,used,External 
14,Accounts,Japan,used,External 
11,Finance,India,used,External 
11,HR,US,used,External 
10,HR,India,used,External 

출력 파일 : 등등

Accounts_India_Internal -- 
12,Accounts,India,free,Internal 

Finance_China_Internal -- 
13,Finance,China,used,Internal 
16,Finance,China,free,Internal 

HR_India_External -- 
12,HR,India,free,External 
10,HR,India,used,External 

HR_China_Internal -- 
19,HR,China,used,Internal 

와 ..

내가 이것을 달성하는 방법을 알려 주시기 바랍니다.

현재로서는이 열 (2,3,5)을 기반으로 파일을 정렬 한 다음 각 레코드에 루프를 실행하고 파일을 만드는 것을 생각하고 있습니다. 파일이 없으면 레코드를 만들고 추가하십시오. 그렇지 않으면 이전 파일을 열고 레코드를 추가하십시오.

쉘 스크립팅 (bash)을 사용하여이 작업을 수행 할 수 있습니까?

+0

내가 정렬 명령을 사용하여 정렬 이 3 개의 컬럼에 기초한 파일. – Anuj

답변

5

쉘 스크립팅 (bash)을 사용하여이를 수행 할 수 있습니까? 당신은 단순히 필드 2, 3을 기반으로 파일을 분할 할 경우

5 당신은 awk으로 신속하게 작업을 수행 할 수 있습니다 이름이 구성되어 파일에 각 라인을 추가

awk -F, '{print >> $2"_"$3"_"$5}' infile.txt 

필드 2, 3, 5

의 예 :

[[email protected]]$ awk -F, '{print >> $2"_"$3"_"$5}' infile.txt 
[[email protected]]$ cat Accounts_India_Internal 
12,Accounts,India,free,Internal 
[[email protected]]$ cat Finance_China_Internal 
13,Finance,China,used,Internal 
16,Finance,China,free,Internal 

아웃 원하는 경우 정렬 된 파일은 먼저 sort을 통해 파일을 실행할 수 있습니다.

sort -k2,3 -k5,5 -t, infile.txt | awk -F, '{print >> $2"_"$3"_"$5}' 
필드 2, 3 라인을 정렬

하고, 5 awk 명령을 전달하기 전에.

파일에 추가 중이므로 출력 파일을 삭제하지 않고 명령을 반복하면 출력 파일에 중복 데이터가 생성됩니다. 이 문제를 해결하고 the chat에 언급 된 추가 요구 사항 (모든 새 파일의 첫 줄을 머리글로 사용)을 포함하려면 this solution을 참조하십시오.

+2

놀라 울 정도로 멋진 awk를 찾고 있습니다. 정렬해야하나요? – TLP

+0

예. 이것은 내가 필요한 것입니다. 감사. awk에 대한 좋은 책/튜토리얼을 나에게 제안 해 주실 수 있습니까? 또한, 내가 그 인쇄물에 어떤 조건을 넣고 싶다면? 열 2가 HR 일 때도 열 4를 포함하여 별도의 파일을 만들어야한다고 가정 해 봅시다. – Anuj

+0

@TLP 아니요, 파일을 분할하는 데 sort가 필요하지 않습니다. 그러나 OP가 최종 결과를 정렬하려면 분할하기 전에 먼저 내용을 정렬하는 것이 더 쉽습니다. –

0

참고 : 코드를 사용하려면 <DATA><>으로 변경하고 파일 이름을 인수로 사용하십시오. Data::Dumper 인쇄물은 데모 용으로 만 제공되며 제거 할 수도 있습니다.

use strict; 
use warnings; 
use Data::Dumper; 

my %h; 
while (<DATA>) { 
    chomp; 
    my @data = split /,/; 
    my $file = join "_", @data[1,2,4]; 
    push @{$h{$file}}, $_; 
} 
print Dumper \%h; 

__DATA__ 
12,Accounts,India,free,Internal 
13,Finance,China,used,Internal 
16,Finance,China,free,Internal 
12,HR,India,free,External 
19,HR,China,used,Internal 
33,Finance,Japan,free,Internal 
39,Accounts,US,used,External 
14,Accounts,Japan,used,External 
11,Finance,India,used,External 
11,HR,US,used,External 
10,HR,India,used,External 

당신과 같이 서브 루틴을 사용할 수, 파일을 인쇄하려면 :

for my $key (keys %h) { 
    print_file($key, $h{$key}; 
} 
sub print_file { 
    my ($file, $data) = @_; 
    open my $fh, ">", $file or die $!; 
    print $fh "$_\n" for @$data; 
} 
1

난 당신이 해당 파일 이름

이 프로그램은 증명에 의해 키가 핸들 파일의 해시를 유지하는 것이 좋습니다.입력 파일은 명령 행에서 매개 변수로 예상된다

use strict; 
use warnings; 

my %fh; 

while (<>) { 
    chomp; 
    my $filename = join '_', (split /,/)[1,2,4]; 
    if (not $fh{$filename}) { 
    open $fh{$filename}, '>', $filename or die "Unable to open '$filename' for output: $!"; 
    print "$filename created\n"; 
    } 
    print { $fh{$filename} } $_, "\n"; 
} 

푸, 다음과 같이 출력

Accounts_India_Internal created 
Finance_China_Internal created 
HR_India_External created 
HR_China_Internal created 
Finance_Japan_Internal created 
Accounts_US_External created 
Accounts_Japan_External created 
Finance_India_External created 
HR_US_External created 
+0

이것은 나에게도 효과적이다. 감사. – Anuj

0

저장 텍스트를 입력 :

cat foo | perl -nle '$k = join "_", (split ",", $_)[1,2,4]; $t{$k} = [@{$t{$k}}, $_]; END{for (keys %t){print join "\n", "$_ --", @{$t{$_}}, undef }}' | csplit -sz - '/^$/' {*} 
관련 문제