여러 txt 파일 병합

여러 txt 파일 병합

여러 개의 txt 파일이 있는데 그 중 3개는 다음과 같습니다.

파일 1:

sample  input filtered
5809378   1      2
5811151   3      4
5811237   5      6

파일 2:

sample  chi tri
5809378  7   8
5811151      
5811237  9   10

파일 3:

sample   bra  doe
5809378  11 
5811151        12
5811237  13    14

이 3개 파일을 첫 번째 열(샘플 ID)을 기반으로 1개 파일로 병합하려고 하므로 출력은 다음과 같습니다.

sample  input  filters  chi  tri   bra   doe
5809378    1     2      7     8     11     0
5811151    3     4      0     0     0     12
5811237    5     6      9     10    13    14

해당 데이터가 없으면 0이 있어야 하며 최악의 경우 빈 탭이 있어야 합니다.

awk 및 Join을 시도했지만 최상의 솔루션을 찾을 수 없습니다. 누구든지 어떤 아이디어가 있습니까?

답변1

내 관점에서 볼 때 file3은 다음 줄 때문에 완전히 정확하지 않습니다.

5811151 12

파일을 읽는 방법에 따라 두 번째 또는 세 번째 열에 숫자 "12"가 있을 수 있습니다(열 구분 기호는 정의되지 않으며 모든 곳에서 다릅니다).

그래도.

a=$(cat file1|awk '{if($2==""){$2="0"};if($3==""){$3="0"}; print $1,$2,$3}'|sort);
for f in file2 file3; do
    b=$(cat $f|awk '{if($2==""){$2="0"};if($3==""){$3="0"}; print $1,$2,$3}'|sort);
    a=$(join -j 1 <(echo "${a}") <(echo "${b}"));
done;
echo "${a}"|sort -n

출력은 다음과 같습니다

sample input filtered chi tri bra doe
5809378 1 2 7 8 11 0
5811151 3 4 0 0 12 0
5811237 5 6 9 10 13 14

그래서 우리는

1) 캡처된 모든 파일이 변환됩니다.

cat file|awk '{if($2==""){$2="0"};if($3==""){$3="0"}; print $1,$2,$3}'|sort

누락된 숫자를 "0"으로 바꾸고 행을 정렬합니다.

2) 루프에서 다음 파일을 가져와 이전 결과에 병합합니다.

join -j 1 file_current file_next

따라서 "for f in file2 file3; do" 행은 "for f in file2 file3 file4 file5 file6; do"와 같이 더 많은 파일을 포함하도록 변경될 수 있습니다.

3) 결과를 인쇄하고 문자열 값에 따라 정렬합니다.(먼저 열 이름을 정렬하고 인쇄합니다.) 필요한 경우 여기에서 출력 형식을 지정할 수도 있습니다.

답변2

파일에 탭으로 구분된 열이 있고(세 번째 줄에서 어떤 열이 비어 있는지 알 수 있음 file3) 예제와 같이 첫 번째 열을 정렬한다고 가정하면 bash 스크립트는 다음과 같습니다.

#!/bin/bash

function fixup() { # Add 0's to blank columns
    awk -v cols="$2" 'BEGIN { FS = OFS = "\t" }
                      { for (i = 1; i <= cols; i++)
                         if ($i == "") $i = 0
                      } 1' "$1"
}

join --header -t$'\t' -j1 \
     <(join --header -t$'\t' -j1 <(fixup "$1" 3) \
                                 <(fixup "$2" 3)) \
     <(fixup "$3" 3)

할 것:

$ ./combine file1 file2 file3
sample  input   filtered        chi     tri     bra     doe
5809378 1       2       7       8       11      0
5811151 3       4       0       0       0       12
5811237 5       6       9       10      13      14

(실제로 GNU coreutils 버전이 필요합니다 join).

답변3

시작 파일이 탭으로 구분되어 있고 빈 필드가 여전히 탭으로 구분되어 있다고 가정하면 awk를 사용하여 누락된 열을 0으로 채울 수 있습니다. 예를 들면 다음과 같습니다.

awk -F'     ' '!$2{$2=0}!$3{$3=0}{print}' file1 > file1-n
awk -F'     ' '!$2{$2=0}!$3{$3=0}{print}' file2 > file3-n
awk -F'     ' '!$2{$2=0}!$3{$3=0}{print}' file3 > file3-n

확실하게 awk -F '<TAB>'. 그런 다음 붙여넣기를 사용하여 병합하고 다른 awk를 사용하여 원하지 않는 열을 필터링할 수 있습니다.

bash-$ paste file1-n file2-n file3-n | awk {'print $1, $2, $3, $5, $6, $8, $9'}
sample input filtered chi tri bra doe
5809378 1 2 7 8 11 0
5811151 3 4 0 0 0 12
5811237 5 6 9 10 13 14

또는 사람의 가독성이 중요한 경우 열을 구분하세요.

bash-$ paste file1-n file2-n file3-n | awk {'printf "%-7s %-5s %-8s %-3s %-3s %-3s %-3s\n", $1, $2, $3, $5, $6, $8, $9'}
sample  input filtered chi tri bra doe
5809378 1     2        7   8   11  0
5811151 3     4        0   0   0   12
5811237 5     6        9   10  13  14

답변4

tab구분 기호 가 있다고 가정하는 또 다른 옵션

0먼저 복식 사이나 텍스트(예: 제목)나 숫자가 없는 줄 끝에 를 삽입하여 tab파일을 수정하세요.$[^[:alnum:]]

TAB=$'\t'; sed -Ei "s/([^[:alnum:]]|${TAB})($|${TAB})/\10\2/g" file*

그럼 그냥 join그 사람들 이야

join --header file2 file3 | join --header file1 - | column -t

산출

sample   input  filtered  chi  tri  bra  doe
5809378  1      2         7    8    11   0
5811151  3      4         0    0    0    12
5811237  5      6         9    10   13   14

관련 정보