С небольшими переделками вашей попытки вы можете сделать что-то вроде ниже.
function revcomp(arg) {
o = ""
for(i = length(arg); i > 0; i--)
o = o c[substr(arg, i, 1)]
return(o)
}
BEGIN {c["A"] = "T"; c["C"] = "G"; c["G"] = "C"; c["T"] = "A" ; OFS="\t"}
{
if($4 == "change") {
$2 = revcomp($2);
$3 = revcomp($3)
}
}1
Ключевым моментом здесь было использование функции revcomp
для принятия аргументов в качестве значений столбца и работы с ними путем итерации с конца. Раньше вы делали по всей строке $0
, т.е. substr($0, i, 1)
, что вызывало бы множество необычных поисков в массиве c
.
Я также взял на себя смелость изменить прототип ваша функция revcomp
принимает входную строку и возвращает перевернутую. Поскольку я не был уверен, как вы собирались использовать в своей первоначальной попытке.
Если вы намереваетесь использовать вышеуказанное в части более крупного скрипта, я бы рекомендовал поместить весь код, как указано выше, в файл сценария, установите интерпретатор she-bang на #!/usr/bin/awk -f
и запустите сценарий как awk -f script.awk input.tsv
Грубая версия bash, реализованная в awk
, как показано ниже. Обратите внимание, что это не чисто и не рекомендуется 1021 * подход. Подробнее см. AllAboutGetline
Как и раньше, вызовите функцию как $2 = revcomp_bash($2)
и $3 = revcomp_bash($3)
function revcomp_bash(arg) {
o = ""
cmd = "printf \"%s\" " arg "| rev | tr \"ATGC\" \"TACG\""
while ( ( cmd | getline o ) > 0 ) {
}
close(cmd);
return(o)
}
Весь ваш код говорит о GNU awk
-ism, поэтому не заботился о преобразовании его в совместимый с POSIX. Вы можете использовать split()
с пустым де-ограничителем вместо length()
, но в спецификации POSIX с радостью сказано, что «эффект пустой строки как значения fs не определен».