나는 이것이 그것을 더 잘 설명한다고 생각합니다.
다음과 같은 행렬 구조(파일)가 있습니다.
파일 1
____ snp1 snp2 snp3 snp4
snp1 1 0.3 0.4 0.5
snp2 0.3 1 0.4 0.5
snp3 0.4 0.4 1 0.5
snp4 0.5 0.5 0.5 1
나는 이것을 바꾸고 싶다파일 1입력하다파일 2:
snp1 snp1 1
snp1 snp2 0.3
snp1 snp3 0.4
snp1 snp4 0.5
snp2 snp2 1
snp2 snp3 0.4
snp2 snp4 0.5
snp3 snp3 1
snp3 snp4 0.5
snp4 snp4 1
제가 이해할 수 있기를 바라지만, 어떤 다른 형식으로 질문해야 할지 모르겠습니다. 내 실제 파일에서는 파일이 file1보다 큽니다.
감사해요.
답변1
원하는 출력에 따라 상부 삼각함수 값만 인쇄합니다.
awk '
NR==1 {
split($0,hdr," "); next
}
{
for (i=NR;i<=NF;i++) {print $1 FS hdr[i] FS $i}
}
' file
snp1 snp1 1
snp1 snp2 0.3
snp1 snp3 0.4
snp1 snp4 0.5
snp2 snp2 1
snp2 snp3 0.4
snp2 snp4 0.5
snp3 snp3 1
snp3 snp4 0.5
snp4 snp4 1
또는 동등하게 Perl을 사용하여
perl -alne '
if ($. == 1) {
@hdr = @F;
} else {
for $i ($.-1 .. $#F) {
print join " ", $F[0], $hdr[$i], @F[$i];
}
}' file
위쪽 삼각형뿐만 아니라 전체 행렬을 원한다면 루프의 시작 인덱스를 수정하여 (awk 버전에서)를 또는 (perl 버전에서) for
로 바꾸십시오.NR
2
$.-1
1
답변2
고쳐 쓰다
이제 제한이 없습니다.
#!/bin/bash
INPUT=File1
declare -a fields
fields=( $(head -n1 "$INPUT") )
i=0
while read -r line; do
values=( $line )
for ((j=++i; j<${#values[@]}; j++)); do
echo -e "${fields[$i]}" "${fields[$j]}"'\t'"${values[$j]}"
done
done < <( tail -n+2 "$INPUT")
답변3
이것은 사용하기 쉬워야 합니다 awk
.
$ awk -f script.awk file1.txt
snp1 snp1 1
snp1 snp2 0.3
snp1 snp3 0.4
snp1 snp4 0.5
snp2 snp1 0.3
snp2 snp2 1
snp2 snp3 0.4
snp2 snp4 0.5
snp3 snp1 0.4
snp3 snp2 0.4
snp3 snp3 1
snp3 snp4 0.5
snp4 snp1 0.5
snp4 snp2 0.5
snp4 snp3 0.5
snp4 snp4 1
콘텐츠 script.awk
. 첫 번째 줄을 건너뛰고 필요에 따라 나머지 부분의 형식을 지정합니다.
$ cat script.awk
{
if (NR == 1) next;
print $1" snp1 "$2;
print $1" snp2 "$3;
print $1" snp3 "$4;
print $1" snp4 "$5;
}
콘텐츠file1.txt
$ cat test.txt
____ snp1 snp2 snp3 snp4
snp1 1 0.3 0.4 0.5
snp2 0.3 1 0.4 0.5
snp3 0.4 0.4 1 0.5
snp4 0.5 0.5 0.5 1
아래와 같이 출력을 새 파일로 리디렉션할 수 있습니다.
awk -f script.awk file1.txt > file2.txt