我有一个看起来像这样的文件:
20:60479_C_T 60479 C T 0 0 0 0 0 1 0 1
20:60522_T_TC 60522 T TC 0 0 0 0 0 0 0
20:60568_A_C 60568 A C 0 0 1 0 0 1
20:60571_C_A 60571 C A 0 1 0 1 0 0
20:60579_G_A 60579 G A 0 0 1 0 0 0
我当前的文件更大,有300万行和3,000列。我想使用列$3
和$4
中的值替换其余列中的0
和1
。所需的输出将是:
20:60479_C_T 60479 C T C C C C C T C T
20:60522_T_TC 60522 T TC T T T T T T T
20:60568_A_C 60568 A C A A C A A C
20:60571_C_A 60571 C A C A C A C C
20:60579_G_A 60579 G A G G A G G G
我知道如何在两列中做到这一点:
awk '{d["0"]=$3; d["1"]=$4; print "20", $1, "0", $2, d[$5], d[$6];}' myfile
但是我不知道如何为所有列自动执行此操作,并且避免手动添加所有列
答案 0 :(得分:1)
$ awk '{d[0]=$3; d[1]=$4; for (i=5; i<=NF; i++) $i=d[$i]} 1' file
20:60479_C_T 60479 C T C C C C C T C T
20:60522_T_TC 60522 T TC T T T T T T T
20:60568_A_C 60568 A C A A C A A C
20:60571_C_A 60571 C A C A C A C C
20:60579_G_A 60579 G A G G A G G G
答案 1 :(得分:0)
在gsub
中使用awk
,您可以尝试以下方法:
$ awk '{d[1]=$1;d[2]=$2;gsub(/0/,$3);gsub(/1/,$4);$1=d[1];$2=d[2];}1' myfile
20:60479_C_T 60479 C T C C C C C T C T
20:60522_T_TC 60522 T TC T T T T T T T
20:60568_A_C 60568 A C A A C A A C
20:60571_C_A 60571 C A C A C A C C
20:60579_G_A 60579 G A G G A G G G
答案 2 :(得分:0)
由于您具有可变的列数,因此您可能可以避免使用类似的东西:
awk <testprog.in '{for (i = 5; i <= NF; i++){$i = $($i+3)}print}'
这里的“魔术”是将$($i+3)
的所有值$i
分配给i
,该值介于5和字段计数(含)之间。
表达式$i+3
将0
和1
分别转换为3
和4
,因此下一步将评估$3
或$4
(例如第一行中的C
和T
),然后使用它们来替换项目。
您的小型测试用例的输出符合预期:
20:60479_C_T 60479 C T C C C C C T C T
20:60522_T_TC 60522 T TC T T T T T T T
20:60568_A_C 60568 A C A A C A A C
20:60571_C_A 60571 C A C A C A C C
20:60579_G_A 60579 G A G G A G G G
您当然需要使用更大的数据集来检查其性能。在我的盒子上,一个三百万行的文件,每个文件有3000个条目,大约需要半小时。
将其与C程序(尽管公认的快速'n'脏,与您的特定输入数据紧密相关,而我通常认为没有必要进行错误检查)进行比较,则只需大约十分钟。
为完整起见,这是C变体,假设它名为prog.c
,则可以使用gcc -o prog prog.c
之类的代码进行编译,并使用./prog <testprog.in
之类的代码运行:
#include <stdio.h>
#include <ctype.h>
static char buff[102040];
static char *getStr(char *buff, int *pSz) {
if (*buff == 0) return NULL;
char *nextBuff = buff;
while ((nextBuff[0] != 0) && isspace(nextBuff[0])) {
nextBuff++;
}
if (*nextBuff == 0) return NULL;
*pSz = 0;
while ((nextBuff[*pSz] != 0) && ! isspace(nextBuff[*pSz])) {
(*pSz)++;
}
return nextBuff;
}
int main(void) {
char *str, *str3, *str4; int sz, sz3, sz4;
while (fgets(buff, sizeof(buff), stdin) != NULL) {
str = getStr(buff, &sz); printf("%*.*s", sz, sz, str);
str = getStr(str + sz, &sz); printf(" %*.*s", sz, sz, str);
str3 = getStr(str + sz, &sz3); printf(" %*.*s", sz3, sz3, str3);
str4 = getStr(str3 + sz3, &sz4); printf(" %*.*s", sz4, sz4, str4);
str = getStr(str4 + sz4, &sz);
while (str != NULL) {
if (*str == '0') {
printf(" %*.*s", sz3, sz3, str3);
} else {
printf(" %*.*s", sz4, sz4, str4);
}
str = getStr(str + sz, &sz);
}
printf("\n");
}
return 0;
}