다음 구조의 file.txt(탭으로 구분)가 있습니다.
cluster01 cluster02 cluster03 ... cluster72
typeA_1 typeA_1 type2 ...
g1_A g4_D g8_H
g2_B g5_E g9_I
g3_C g6_F g10_J
g7_G g11_K
g12_L
파일에는 72개의 열이 있으며 각 열에는 가변 길이가 있습니다.
file.txt를 다음과 같이 newfile.txt로 다시 포맷하고 싶습니다.
g1_A cluster01 typeA_1
g2_B cluster01 typeA_1
g3_C cluster01 typeA_1
g4_D cluster02 typeA_1
g5_E cluster02 typeA_1
g6_F cluster02 typeA_1
g7_G cluster02 typeA_1
g8_H cluster03 type2
g9_I cluster03 type2
g10_J cluster03 type2
g11_K cluster03 type2
g12_L cluster03 type2
답변1
또 다른 간단한awk
+sed
얼마나 많은 열이 있는지 외에 3줄 이상의 들여쓰기가 있는 방법입니다.
awk 'NR==1{split($0, clstr, /#/)} NR==2{split($0, type, /#/)}
NR>2 {split($0, g, /#/); for (x in g) if(g[x]!="") print g[x], clstr[x], type[x]
}' <(sed -E 's/\t/#/g' infile)
설명하다:
NR==1{split($0, clstr, /#/)}
: 우리는 사용했었다awk 분할() 함수이는 나뉜다문자열/라인/레코드($0
awk로 전체 줄을 가리키며끈여기서)은 해시로 구분된 조각으로 나누어지고 첫 번째 레코드에만 as 조건이 있는#
배열에 저장됩니다 .clstr
NR==1
NR==2{split($0, type, /#/)}
: 위에서 설명한 것과 동일한 작업을 수행하고 이라는 배열에 저장되며type
as 조건이 있는 두 번째 레코드에서만 실행됩니다NR==2
.NR>2{ ... }
: 이 코드 블록은 해당 코드 블록이 있는 레코드/행에 대해 실행됩니다.질소수량오른쪽레코드수>2split($0, g, /#/)
: 첫 번째 및 두 번째 항목과 동일하며 이라는 배열에 저장됩니다g
.for (x in g) if(g[x]!="") print g[x], clstr[x], type[x]
: 이제 배열 인덱스의 요소를 반복g
하고 해당 값이 null이 아닌 경우 먼저 배열 에서if(g[x]!="")
해당 값을 인쇄한g[x]
다음 배열에 해당 값을 인쇄합니다.clstr
type
입력을 처리하기 전에 모든 항목을 교체합니다.탭해시 문자를 사용하여
#
(다른 문자를 사용할 수 있지만 파일에 해당 문자가 나타나지 않는지 확인해야 함) awk에 전달합니다.<(sed 's/\t/#/g' infile) ## or <(tr '\t' '#'< infile)
입력하다(상표분리됨):
cluster01 cluster02 cluster03 ... cluster72
typeA_1 typeA_1 type2 ...
g1_A g4_D g8_H
g2_B g5_E g9_I
g3_C g6_F g10_J
g7_G g11_K
g12_L
산출:
g1_A cluster01 typeA_1
g4_D cluster02 typeA_1
g8_H cluster03 type2
g2_B cluster01 typeA_1
g5_E cluster02 typeA_1
g9_I cluster03 type2
g3_C cluster01 typeA_1
g6_F cluster02 typeA_1
g10_J cluster03 type2
g7_G cluster02 typeA_1
g11_K cluster03 type2
g12_L cluster03 type2
답변2
Awk
고정 솔루션"필드는 내림차순으로 나타납니다"게임 1부터 게임 3까지:
awk 'NR == 1 {
group1 = $1; group2 = $2; group3 = $3
}
NR == 2 {
group1 = group1 OFS $1;
group2 = group2 OFS $2;
group3 = group3 OFS $3
}
NR > 2 {
if (NF == 3) { cl1[NR - 2] = $1 }
if (NF >= 2) { cl2[NR - 2] = $(NF - 1) }
cl3[NR - 2] = $(NF)
}
END {
traverse(cl1, group1);
traverse(cl2, group2);
traverse(cl3, group3)
}
function traverse(cl, gr) {
len = length(cl);
for (i = 1; i <= len; i++) {
print cl[i], gr
}
}' OFS='\t' file
산출:
g1 cluster01 typeA
g2 cluster01 typeA
g3 cluster01 typeA
g4 cluster02 typeA
g5 cluster02 typeA
g6 cluster02 typeA
g7 cluster02 typeA
g8 cluster03 typeB
g9 cluster03 typeB
g10 cluster03 typeB
g11 cluster03 typeB
g12 cluster03 typeB