내 문제는 다음과 유사합니다.첫 번째 열 값을 기준으로 여러 열 병합
여러 개의 파일(10개 이상)이 있고 이를 하나의 출력 파일로 병합/결합하고 싶습니다. 예를 들면 다음과 같습니다.
파일 1
2000 0.0202094
2001 0.0225532
2002 0.02553
2003 0.0261099
2006 0.028843
파일 2
2000 0.0343179
2003 0.039579
2004 0.0412106
2006 0.041264
파일 3
2001 0.03
2004 0.068689
2006 0.0645474
모든 파일은 동일한 두 개의 열을 가지며 길이가 다양합니다. 열 항목이 없으면(하나 이상의 파일에서 누락됨) 1이 필요합니다. 파일에 항목이 없으면(예: 2005) 출력을 원하지 않습니다.
원하는 출력은 다음과 같습니다.
file1 file2 file3
2000 0.0202094 0.0343179 1
2001 0.0225532 1 0.03
2002 0.02553 1 1
2003 0.0261099 0.0395799 1
2004 1 0.0412106 0.0686893
2006 0.028843 0.041264 0.0645474
다른 질문에 대한 답변에 제공된 awk 코드를 수정해 보았지만 해결이 불가능한 것 같습니다.
답변1
사용 join
:
join -a1 -a2 -e 1 -o auto <(join -a1 -a2 -e 1 -o auto file1 file2) file3
에서 본남자들이 가입하다
-파일 번호
또한 FILENUM이 FILE1 또는 FILE2에 해당하는 FILENUM이 1 또는 2인 파일 FILENUM에서 페어링할 수 없는 줄을 인쇄합니다.-e 비어 있음
누락된 입력 필드를 EMPTY로 바꾸기-o 형식
출력 행을 작성할 때 FORMAT을 따르세요.
FORMAT이 "auto" 키워드인 경우 각 파일의 첫 번째 줄은 줄당 출력되는 필드 수를 결정합니다.
참고: 조인에는 정렬된 입력이 필요하므로 이러한 입력이 정렬되지 않은 경우(주어진 샘플에 있음) 먼저 정렬하십시오. 예:
join -a1 -a2 -e 1 -o auto \
<(join -a1 -a2 -e 1 -o auto <(sort file1) <(sort file2)) \
<(sort file3)
여러 파일에 적용하려면:
처음 두 파일을 연결하고 출력을 세 번째 파일에 저장합니다.
join.tmp
:join -a1 -a2 -e 1 -o auto file1 file2 >join.tmp
next는 나머지 파일과 업데이트를 반복합니다.
join.tmp
각 실행에 대한 파일:for file in rest_files*; do join -a1 -a2 -e 1 -o auto join.tmp "$file" >join.tmp.1 mv join.tmp.1 join.tmp done
드디어 너의 것
join.tmp
최종 연결 결과가 됩니다.
제목과 함께 인쇄:
$ hdr() { awk 'FNR==1{ print "\0", FILENAME }1' "$1"; }
$ join -a1 -a2 -e 1 -o auto \
<(join -a1 -a2 -e 1 -o auto <( hdr file1) <(hdr file2)) \
<(hdr file3) |tr -d '\0'
다중 파일 버전의 경우:
$ hdr() { awk 'FNR==1{ print "\0", FILENAME }1' "$1"; }
$ join -a1 -a2 -e 1 -o auto <(hdr file1) <(hdr file2) >join.tmp
$ for file in rest_files*; do
join -a1 -a2 -e 1 -o auto join.tmp <(hdr "$file") >join.tmp.1
mv join.tmp.1 join.tmp
done
$ tr -d '\0' <join.tmp >final.file
답변2
약간 투박하지만 이 awk
코드는 작동합니다. 사용하는 옵션의사 다차원 배열배열 인덱스와 SUBSEP 연결. 모든 데이터를 RAM에 보관하므로 이 경우에는 제한됩니다.
{x[$1]=$1 ; file[FILENAME]=FILENAME ; y[$1,FILENAME]=$2}
END { for (i in file) { printf "\t%s",file[i] } ; printf "\n",""
for (i in x) { printf "%s",x[i]
for (j in file) { if (y[x[i],file[j]] != "")
{ printf"\t%s",y[x[i],file[j]] }
else { printf"\t%s","1"}
}
printf "\n",""
}
}
출력은 탭으로만 구분됩니다. 고정 형식의 경우 printf 명령을 그에 맞게 조정해야 합니다.
file1 file2 file3
2000 0.0202094 0.0343179 1
2001 0.0225532 1 0.03
2002 0.02553 1 1
2003 0.0261099 0.039579 1
2004 1 0.0412106 0.068689
2006 0.028843 0.041264 0.0645474