첫 번째 열을 기준으로 여러 파일을 하나의 파일에 붙여넣습니다.

첫 번째 열을 기준으로 여러 파일을 하나의 파일에 붙여넣습니다.

파일이 여러 개 있고 각 파일의 첫 번째 열을 기준으로 병합해야 합니다.

파일 1:

foo  12  
jhdfeg 25  
kjfdgkl 37

파일 2:

foo 23  
jhdfeg 45

파일 3:

foo 35  
djhf 37  

출력은 다음과 같아야합니다

        file1 file2  file3  
foo     12    23     35  
jhdfeg  25    45     0  
kjfdgkl 37    0      0  
djhf    0     0      37

답변1

방법:

joiner.awk스크립트:

#!/bin/awk -f
BEGIN { 
    f1=ARGV[1]; f2=ARGV[2]; f3=ARGV[3]     # the 1st, 2nd and 3rd file names respectively
    printf("%10s\t%s\t%s\t%s\n", "", f1, f2, f3)   # printing header
}
{ a[$1][FILENAME]=$2 }    # accumulating values
END {
    for (i in a) {
        printf("%-10s\t%d\t%d\t%d\n", i, a[i][f1], a[i][f2], a[i][f3]) 
    }
}

용법:

awk -f joiner.awk file1 file2 file3

산출:

          file1 fil2 file3
kjfdgkl     37  0   0
foo         12  23  35
djhf        0   0   37
jhdfeg      25  45  0

답변2

perl -F'\s+' -lane '

   $. == 1 and @ARGC = ($ARGV, @ARGV);       # initialize the @ARGC array

   exists $h{$F[0]} or $h[keys %h] = $F[0];  # needed to remember order

   $h{$F[0]}->[@ARGC-@ARGV-1] = $F[1];       # populate hash

   END {
      $, = "\t";           # set the OFS to TAB

      print q//, @ARGC;    # print the first line with filenames

      for my $key (@h) {   # print remaninig lines with data
         print $key,
            map { $h{$key}->[$_] // 0 } 0 .. $#ARGC;
      }
   }

' file1 file2 file3 # ... you can give as many files here

산출

        file1   file2   file3
foo     12      23      35
jhdfeg  25      45      0
kjfdgkl 37      0       0
djhf    0       0       37

답변3

귀하의 예와 같이 파일이 3개 있는 경우 join마법을 사용하여 이 작업을 수행할 수 있습니다. 먼저 탭으로 구분된 파일 이름을 출력 파일에 씁니다.

for i in File*; do printf "\t%s" "$i" >> RES; done

실제 결과에 대해 빈 줄을 추가합니다.

printf '\n' >> RES

joinon을 사용 File1하고 File2출력을 임시 파일로 리디렉션합니다.

join  -a1 -a2  -e0 <(sort File1) -o 0 1.2 2.2 <(sort File2) > TEMP_FILE

이제 위 명령의 출력을 다시 사용하십시오 File3(여기서 파이프( )를 사용할 수도 있습니다 |).

join  -a1 -a2  -e0 <(sort TEMP_FILE) -o 0 1.2 1.3 2.2 <(sort File3) >> RES

공백을 탭으로 바꾸십시오 RES.

tr ' ' '\t' < RES > FINAL_RES

결과는 다음 위치에 있습니다 FINAL_RES.

$ cat FINAL_RES
        File1   File2   File3
foo     12      23      35
jhdfeg  25      45      0
kjfdgkl 37      0       0

답변4

파일 수와 관계없이 보다 일반적인 접근 방식은 다음과 같습니다 sed.

sed '1{x;s/$/_/;x;}
  /foo/{x;s/_/ 0_/g;x;}
  G;s/^\([a-z]*\)  *\([0-9]*\).*\n\(.*_\)\1\([^_]*\)0/\3\1\4\2/
  s/^\([a-z]*\) *\([0-9]*\).*\n\([^_]*\)0_\(.*\)/\30_\4\1\3\2_/
  $! {h;d;}
  s/[^_]*_//
  y/_/\n/' file*

이는 foo예제에서 볼 수 있듯이 해당 줄로 시작하는 모든 파일에 의존합니다.

sed이제 작동 방식, 패턴 공간, 공간 유지에 대한 기본 사항을 알았으므로 설명은 다음과 같습니다.

주요 아이디어는 예약된 공간에 전체 출력 테이블을 구축하는 것입니다. 각 행에 대해 예약된 공간에는 해당 지점의 테이블과 새 행에 필요한 템플릿 행이 포함됩니다. _처리 중에 줄 구분 기호로 사용합니다 . 이제 단계별로:

1{x;s/$/_/;x;}

그러면 _템플릿 줄의 시작 부분으로 단일을 사용하여 예약된 공간이 초기화됩니다.

/foo/{x;s/_/ 0_/g;x;}

/foo/foo새 파일의 시작을 나타내는 포함 줄을 지정합니다 . 이 경우 다음 명령이 실행됩니다 {}. 예약된 공간의 모든 행(실제 테이블 행 및 템플릿 행)이 0추가됩니다. 나중에 해당 줄에 대한 키워드를 발견하면 0올바른 숫자로 대체됩니다. 키워드가 나타나지 않으면 0유지됩니다.

G;s/^\([a-z]*\) *\([0-9]*\).*\n\(.*_\)\1\([^_]*\)0/\3\1\4\2/

'G'는 예약된 공간을 패턴 공간에 추가합니다. 명령 s은 네 부분으로 구성됩니다 . 첫 번째 부분에는 키워드가 포함되고, 두 번째 부분에는 값이 포함되며, 세 번째 부분에는 키워드가 두 번째 나타날 때까지(역 참조 ) \(\)개행 문자 뒤의 모든 항목이 포함됩니다(따라서 이는 예약된 공간에서 추가된 테이블입니다). \1. 네 번째 항목은 마지막 항목을 제외한 행의 모든 ​​항목을 소유합니다 0. 따라서 해당 키워드가 포함된 기존 행을 찾고 0모든 것을 개행 문자에 넣고 업데이트된 테이블을 유지합니다.

s/^\([a-z]*\) *\([0-9]*\).*\n\([^_]*\)0_\(.*\)/\30_\4\1\3\2_/

또 다른 일치 항목에는 newline이 포함되어 있으므로 \n테이블에서 키워드를 찾지 못했다는 것을 알 수 있습니다(그렇지 않으면 이전 줄에서 줄바꿈이 제거되었을 것입니다. 따라서 이번에는 키워드로 구성된 새 줄을 끝에 추가합니다. 이것이 바로 템플릿 행의 비결입니다. 0새 파일마다 열을 추가하므로 열을 제거하면 0각 파일에 대해 키워드가 없는 열이 하나씩 있게 됩니다.0

$! {h;d;}

마지막 행이 아닌 경우 수정된 테이블을 다시 예약된 공간( h)으로 이동하고 다시 시작합니다( d).

s/[^_]*_//

마지막 행의 경우 템플릿 행이 제거됩니다.

y/_/\n/

_이는 개행 문자를 대체합니다 . 또한 원하는 경우 공백을 탭으로 바꿀 수 있습니다.

편집하다

모든 파일이 해당 줄로 시작한다는 가정이 잘못된 경우 각 파일의 시작 부분에 추가 줄을 추가하고 전체 콘텐츠를 다음으로 스트리밍하는 등 새 파일이 시작되는 시기를 foo알 수 있는 다른 방법이 필요합니다 .sedsed

for file in file*; do
  echo Start of $file
  cat $file
done | sed '1{x;s/$/__/;x;}
  /Start of/{G;s/_/ 0_/g;s/Start of \(.*\)\n\([^_]*\)_\([^_]*\) 0/\2_\3 \1/;x;d;}
  G;l;s/^\([a-z]*\)  *\([0-9]*\).*\n\(.*_\)\1\([^_]*\)0/\3\1\4\2/
  l;s/^\([a-z]*\) *\([0-9]*\).*\n\([^_]*\)0_\(.*\)/\3 0_\4\1\3\2_/
  $! {h;d;}
  s/[^_]*_//
  y/_/\n/'

이 버전은 또한 모든 파일 이름을 열 헤더로 사용하여 테이블의 헤더 행을 생성합니다.

관련 정보