마스터 파일을 기반으로 다양한 버전의 텍스트 파일의 제목과 데이터를 재정렬합니다.

마스터 파일을 기반으로 다양한 버전의 텍스트 파일의 제목과 데이터를 재정렬합니다.

참조 마스터 파일에 지정된 필드|순서에 따라 파이프로 구분된 여러 텍스트 파일의 데이터(제목 및 세부 정보)를 재정렬하고 쉘 스크립트를 사용하여 단일 출력 파일을 생성하고 싶습니다. 아래 코드가 있지만 예상대로 작동하지 않습니다. while 루프는 마스터에서 열의 순서를 가져와 다시 정렬합니다. 그러나 고려해야 할 다음과 같은 기능이 있습니다.쉘 스크립트/awk에서 솔루션 찾기.

참조 마스터 파일과 비교하여 입력 파일에 누락되거나 새 열이 있을 수 있습니다. 참조 마스터 파일의 순서는 나중에 변경될 수 있으며 열은 어느 위치에서나 추가되거나 제거될 수 있습니다. 여러 입력 파일을 허용합니다.

입력 파일 A 예시:

Name|Amount|Vehicle|City|Visits|Indicator

Jack|123.22|Volkswagen|Altamonte|1|Y

Sam|23.1|Audi||3|N

|21.4|Ford|NewYork||Y

입력 파일 B 예시:

Suffix|Name|Visits|Vehicle|State|Indicator|City|Gender

Mr|Jack|1|Volkswagen|NJ|Y|Hoboken|M

Mr|Rob|6|Buick||N|Stamford|

기본 파일을 참조하십시오.

상태|1

도시|2

차량|3

성별|4

이름|5

수량|6

결과물 파일:

State|City|Vehicle|Gender|Name|Amount

|Altamonte|Volkswagen||Jack|123.22

||Audi||Sam|23.1

|NewYork|Ford|||21.4

NJ|Hoboken|Volkswagen|M|Jack|

|Stamford|Buick||Rob|

쉘 스크립트:

/*Comment::Reads the input column names and assign number based on order for*/
/*Comment::each column in the input file.*/
cat infile.out | head -1 | tr -s '|' '\n' | cat -n > infile_tmp.out
rm -f final.out

/*Comment:compare the master file column names with input file column names and 
/*Comment:get the column number from master file*/ 
while read line; do 
touch final.out
vChkClmn=`echo $line | cut -d "|" -f1`
vMasterClm=`grep -i $vChkClmn infile_tmp.out | cut -d " " -f1`
echo "$vMasterClm" >> final.out
done < master_file.out

rm -f final_master_list.out
echo `cat final.out` | sed 's/[^ ]* */\$&/g' | sed 's/ /\,/g' > final_master_list.out
vOrder=`cat final_master_list.out`
echo "Value of order is $vOrder"
awk -F\| '{print '$vOrder'}' OFS=\| infile.out

답변1

#!/usr/bin/perl

use strict;

my $master = shift;
open(M,"<","$master") || die "couldn't open $master:$!\n";
chomp(my @master = split(/\|/,<M>));
close(M);

print join("|",@master),"\n";

my @fields=();
while (<>) {
  if ($. == 1) {
    chomp(@fields = split /\|/);
    next;
  };

  chomp(my @row = split/\|/);
  my @out = ();

  foreach my $m (@master) {
    my $o='';
    for (my $i=0; $i < $#row; $i++) {
      if ($fields[$i] eq $m) {
        $o = $row[$i];
      };
    }
    push @out, $o;
  };

  print join("|",@out),"\n";
} continue {
    close ARGV if eof; # reset the line counter after each input file
}

이는 참조 마스터 파일을 읽습니다(여기서~ 해야 하다명령줄의 첫 번째 인수)를 필드 이름(@master)이 포함된 배열로 분할합니다.

그런 다음 나머지 파일 이름 매개변수를 모두 읽고 다음을 수행합니다.

  • 파일의 첫 번째 줄인 경우 줄을 배열로 분할하여 필드 헤더를 가져옵니다.@fields
  • 그렇지 않으면 행을 배열로 분할 @row하고 @master 및 의 각 요소를 반복합니다 @row. 그 자리에서이름행 요소 중 하나가 @master의 요소와 일치하고 필드의 요소를 추가합니다.출력 배열(@out)에 추가하고, 그렇지 않으면 빈 문자열을 추가합니다.
  • @out문자로 연결된 배열을 인쇄합니다 |.
  • 배열 @out은 각 입력 라인에서 비어 있도록 재설정됩니다.

예를 들어 다른 이름으로 저장하고 rearrange.pl실행 가능하게 만들고 chmod +x rearrange.pl다음과 같이 실행합니다.

$ ./rearrange.pl master.txt input1.txt input2.txt 
State|City|Vehicle|Gender|Name|Amount
|Altamonte|Volkswagen||Jack|123.22
||Audi||Sam|23.1
|NewYork|Ford|||21.4
NJ|Hoboken|Volkswagen||Jack|
|Stamford|Buick||Rob|

참고: 이는 두 개의 입력 파일에만 국한되지 않습니다. 한 번에 원하는 만큼의 입력 파일을 처리할 수 있습니다. 두 가지 제한사항만 있습니다.

  1. 기본 참조 파일(예 master.txt: )~ 해야 하다명령줄의 첫 번째 매개변수입니다.

  2. 입력 파일이 하나 이상 있어야 합니다.또는입력 파일은 스크립트로 파이프되어야 합니다.

    참고: 하나의 파일만 입력할 수 있습니다.관로- 여러 파일이 파이프로 연결된 경우 스크립트는 어떤 줄이 헤더 줄이고 어떤 줄이 데이터 줄인지 알 수 없습니다.

관련 정보