TSV 파일을 추가하는 방법, 예:
TSV
c 7 r z
d 6 s w
f 1 f f
b 8 p y
a 9 q x
TSV
a q a
c r ccc
b p bb
0 0 0
d s dddd
where a$1,a$3==b$1,b$2
여기서는 열 단위로 "결합" 하고 나머지 (a$2,a$4,b$3)를 표시하고 싶습니다 .
6 w dddd
9 x a
8 y bb
7 z ccc
문제는 gawk에서 이것을 어떻게 하시겠습니까?
줄의 순서가 요구 사항을 충족하지 않습니다.(출력에서. 입력에서 행의 순서는 정의되지 않았으며 a.tsv 및 b.tsv에서 다를 수 있습니다. 관계형 데이터베이스의 행과 마찬가지로 순서가 없습니다.)
고유성 설명key={a$1,a$3}
:처음에는 " .As 의 고유성"을 가정했습니다.글렌 잭맨참고 - 키를 기반으로 고유한 행을 허용하지 않으므로 원래 문제 설명에서 가정할 수 없습니다. 감사합니다.글렌.
답변1
join
이 명령은 하나의 필드만 추가할 수 있는 것 같습니다 .1,2], 그래서:
awk '
BEGIN {FS=OFS="\t"}
NR==FNR {a[$1 FS $3] = $2 FS $4; next}
$1 FS $2 in a {print a[$1 FS $2], $3}
' a.tsv b.tsv
의견으로 인한 업데이트: 주어진 키가 고유하지 않기 때문에 "a.tsv"에서 여러 항목을 작성하는 기술이 있습니다.
awk '
BEGIN {FS=OFS="\t"}
NR==FNR {
key = $1 FS $3
if (key in a)
a[key] = a[key] "\n" $2 FS $4
else
a[key] = $2 FS $4
next
}
$1 FS $2 in a {
split(a[$1 FS $2], ary, /\n/)
for (idx in ary)
print ary[idx], $3
}
' a.tsv b.tsv
답변2
나는 작업을 두 개의 다른 프로그램으로 나누었습니다.
사용가입(1)두 파일 연결
어크(1)또는절단(1)불필요한 열 제거
답변3
잘은 모르겠지만 awk
텍스트 파일의 필드를 처리하기 위해 특별히 설계되었기 때문에 작업이 잘 될 것이라고 생각했지만 (? join
)ktf설명), 여기에 표준 유닉스 도구를 사용하는 솔루션이 있습니다: join
and cut
and paste
and sort
-- 많은 "and"가 있지만 작동하며 awk
왜 더 나은지에 대한 예 역할을 합니다 :)... 주로 방법에 대해 넣었습니다. 비교 요소 .
join -t $'\t' -o 1.2 1.3 2.2 \
<(paste <(paste <(cut -f1 a.tsv) \
<(cut -f3 a.tsv) \
| tr '\t' '\0' ) \
<(cut -f2 a.tsv) \
<(cut -f4 a.tsv) \
| sort ) \
<(paste <(paste <(cut -f1 b.tsv) \
<(cut -f2 b.tsv) \
| tr '\t' '\0' ) \
<(cut -f3 b.tsv) \
| sort )
답변4
마침내 나는 그것을 할 수 있었다. 그래서 내 솔루션을 공유합니다.
awk '
BEGIN {
FS=OFS="\t"
while ((getline < "a.tsv") > 0){
a2[$1,$3] = $2; a4[$1,$3] = $4
}
}
($1,$2) in a2 { print a2[$1,$2] FS a4[$1,$2] FS $3 }' < b.tsv
생산하다:
9 x a
7 z ccc
8 y bb
6 w dddd
이 솔루션은 다음과 같습니다.
- 입력 라인의 순서를 가정하지 않습니다.
- 일부 줄에 다른 파일과 일치하는 항목이 없을 때 작동합니다.
- 다음 행은 다음
a.tsv
과 같다고 가정합니다.key = {a$1,a$3}
관심있는 분들을 위해오른쪽 가입if( ($1,$2) in a2)
, 명세서를 삭제하면 됩니다 . 관심있는 분들을 위해왼쪽 조인, "올바른 조인" 버전을 수행하고 a.tsv를 b.tsv로 바꾸십시오(그리고 이에 따라 코드를 변경하십시오).
고유성 설명: 처럼글렌 잭맨에 a.tsv
따르면 이 줄은 고유하지 않을 수 있으므로 key={a$1,a$3}
그의 솔루션을 확인하고 싶을 수도 있습니다.