awk '$1=="ID" {print $0 "\tINFOextra"; next}; NF { info=$6; gsub(/.*;DP4=|;MQ=.*/, "", info); split(info, a, /,/); print $0 "\t" (a[3]+a[4])/(a[1]+a[2]+a[3]+a[4])}' inputfile.txt > outputfile.txt
# then check the content outputfile.txt and rename it if important
Как видите, решение очень похоже на ответ на ваш предыдущий вопрос, и совсем не дольше. Это потому, что awk очень хорошо настроен для решения таких проблем, как ваша. Я рекомендую взглянуть на его страницу руководства (http://linux.die.net/man/1/awk), чтобы увидеть, насколько она проста по сравнению с другими (и более универсальными) языками.
Если несколько входных файлов должны быть обработаны в несколько выходных файлов с соответствующими именами, параметры следующие:
- создать цикл в оболочке и запустить процесс awk для каждого файла, один за другим
make awk записывает вывод в файлы, имена которых зависят от имени текущего входного файла, информация о котором хранится в переменной FILENAME awk, которая автоматически устанавливается во время процесса. Внутри перенаправления кода awk может использоваться тот же синтаксис и тот же результат, что и в оболочке:
awk '$ 1 == "ID" {print $ 0 "\tINFOextra"> FILENAME ".out"; следующий}; NF {info = $ 6; GSUB (/.*; DP4 = |; MQ =. */, "", Info); split (информация, а, /, /); выведите $ 0 "\t" (a [3]+a [4]) /(a [1]+a [2]+a [3]+a [4])> FILENAME ".out"} 'inputfile1.txt inputfile2.txt
Здесь каждый экземпляр inputfileN.txt будет иметь соответствующий файл inputfileN.txt.out. FILENAME - простая строка, поэтому любые манипуляции с выходными файлами допустимы.
Когда спецификация усложняется так, что дополнительное поле должно появиться во внутренней позиции (не в начале или в конце), следует создать подпрограмму (называемую функцией в awk) для создания выходных строк. Эта функция перебирает все поля, печатает их как обычно, но там, где должно появиться дополнительное поле, она записывает это после n-го 1-го и перед n-м полем, делая его n-ным. Теперь стоит поместить код awk в отдельный файл:
$ cat bio.awk
function myprint( str) {
for (i=1; i<=NF; ++i) {
printf "%s", $i > FILENAME ".out"
if (i==44)
printf "\t%s", str >> FILENAME ".out"
if (i!=NF)
printf "\t" >> FILENAME ".out"
}
print "" >> FILENAME ".out"
}
$1=="ID" {
myprint( "INFOextra")
next
}
NF {
info=$6
gsub(/.*;DP4=|;MQ=.*/, "", info)
split(info, a, /,/)
myprint( (a[3]+a[4])/(a[1]+a[2]+a[3]+a[4]) )
}
Вызов этого приведет к более короткой и чистой командной строке:
awk -f bio.awk inputfile1.txt inputfile2.txt