Поскольку у вас есть переменное количество столбцов, вы, вероятно, можете получить что-то вроде:
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 (хотя она, по общему признанию, quick'n'dirty, сильно привязана к вашим специфическим входным данным, без того, что я обычно считаю необходимой проверкой ошибок), которая занимает всего около десяти минут.
Для полноты, вот вариант 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;
}