#linux #awk #replace
#linux #awk #заменить
Вопрос:
Я пытаюсь заменить значения в столбце 1 файла 1 с помощью таблицы поиска. Образец (разделенный табуляцией):
chr1 1243 A T 0.14
chr5 1432 G C 0.0006
chr10 731 T C 0.9421
chr11 98234 T G .000032
chr12 1284 A T 0.93428
chr17 941 G T 0.1111
chr19 134325 T C 0.00001
chr21 9824 T C 0.9
Таблица подстановки:
chr1 NC_000001.11
chr2 NC_000002.12
chr3 NC_000003.12
chr4 NC_000004.12
chr5 NC_000005.10
chr6 NC_000006.12
chr7 NC_000007.14
chr8 NC_000008.11
chr9 NC_000009.12
chr10 NC_000010.11
chr11 NC_000011.10
chr12 NC_000012.12
chr13 NC_000013.11
chr14 NC_000014.9
chr15 NC_000015.10
chr16 NC_000016.10
chr17 NC_000017.11
chr18 NC_000018.10
chr19 NC_000019.10
chr20 NC_000020.11
chr21 NC_000021.9
chr22 NC_000022.11
используемый сценарий:
awk 'FNR==NR{a[$1]=$2;next} {for (i in a)sub(i,a[i]);print' lookup.txt file1 > new_table.txt
вывод с комментарием, какая строка правильная / неправильная (с правильным ответом в скобках):
NC_000001.11 1243 A T 0.14 #correct
NC_000005.10 1432 G C 0.0006 #correct
NC_000001.110 731 T C 0.9421 #incorrect (NC_000010.11)
NC_000001.111 98234 T G .000032 #incorrect (NC_000011.10)
NC_000012.12 1284 A T 0.93428 #correct
NC_000001.117 941 G T 0.1111 #incorrect (NC_000017.11)
NC_000001.119 134325 T C 0.00001 #incorrect (NC_000019.10)
NC_000021.9 9824 T C 0.9 #correct
Я не понимаю, почему это не работает, и был бы рад любой помощи с awk-скриптом. Я думал, что это только те, у которых двузначные цифры, например, chr17, но тогда chr21, кажется, работает нормально.
Большое спасибо
Комментарии:
1. Не могли бы вы, пожалуйста, исправить свои образцы,
NC_000005.101432
которых нет в показанных вами файлах примеров, пожалуйста, исправьте образец ввода и ожидаемого результата в вашем вопросе и сообщите нам об этом.2. Есть ли у вас возврат каретки DOS в одном или обоих файлах?
3. @tripleee я так не думаю. Эти файлы только из Linux, и я переформатировал их все, чтобы разделить табуляцию с помощью функции column -t
Ответ №1:
Разве это не должно быть:
awk 'FNR==NR{a[$1]=$2;next}{$1=a[$1]}1' lookup.txt file1
?
Выходной сигнал:
NC_000001.11 1243 A T 0.14
NC_000005.10 1432 G C 0.0006
NC_000010.11 731 T C 0.9421
NC_000011.10 98234 T G .000032
NC_000012.12 1284 A T 0.93428
NC_000017.11 941 G T 0.1111
NC_000019.10 134325 T C 0.00001
NC_000021.9 9824 T C 0.9
Объяснение:
# true as long as we are reading the first file, lookup.txt
FNR==NR {
# create a lookup array 'a' indexed by field 1 of lookup txt
a[$1]=$2
# don't process further actions
next
}
# because of the 'next' statement above, this will be only executed
# when we are processing the second file, file1
{
# translate field 1. use the value from the lookup array
$1=a[$1]
}
# always true. print the line
1
PS: Если есть вероятность, что записи не могут быть найдены в таблице поиска, вы можете использовать для них специальный текст:
awk 'FNR==NR{a[$1]=$2;next}{$1=($1 in a)?a[$1]:"NOT FOUND "$1}1' lookup.txt file1
Ответ №2:
Я полагаю sub
, что это может быть проблемой в попытке OP, не проверенной тщательно, это можно было бы сделать просто:
awk 'FNR==NR{arr[$1]=$2;next} ($1 in arr){first=$1;$1="";print arr[first],$0}' lookup_table Input_file
Проблема с попыткой OP (только для понимания того, что НЕ следует запускать для получения результатов показанных образцов): Хотя показанный код OP не выглядит полным, чтобы выяснить, почему он выдает неверный вывод в соответствии с вопросом OP, я написал это следующим образом.
awk 'FNR==NR{a[$1]=$2;next} {for (i in a){line=$0;if(sub(i,a[i])){print (Previous line)line">>>(array key)"i"....(array value)"a[i]"............(new line)"$0}}}' lookup_table Input_file
Поэтому всякий раз, когда происходит правильная замена, только тогда выводится строка следующим образом, где мы могли видеть, что происходит не так с кодом OP.
chr1 1243 A T 0.14 chr1 1243 A T 0.14 >>>(array key)chr1....(array value)NC_000001.11............(new line)NC_000001.11 1243 A T 0.14
chr5 1432 G C 0.0006chr5 1432 G C 0.0006>>>(array key)chr5....(array value)NC_000005.10............(new line)NC_000005.10 1432 G C 0.0006
chr10 731 T C 0.9421chr10 731 T C 0.9421>>>(array key)chr1....(array value)NC_000001.11............(new line)NC_000001.110 731 T C 0.9421
chr11 98234 T G .000032chr11 98234 T G .000032>>>(array key)chr1....(array value)NC_000001.11............(new line)NC_000001.111 98234 T G .000032
chr12 1284 A T 0.93428chr12 1284 A T 0.93428>>>(array key)chr12....(array value)NC_000012.12............(new line)NC_000012.12 1284 A T 0.93428
chr17 941 G T 0.1111chr17 941 G T 0.1111>>>(array key)chr1....(array value)NC_000001.11............(new line)NC_000001.117 941 G T 0.1111
chr19 134325 T C 0.00001chr19 134325 T C 0.00001>>>(array key)chr1....(array value)NC_000001.11............(new line)NC_000001.119 134325 T C 0.00001
chr21 9824 T C 0.9chr21 9824 T C 0.9>>>(array key)chr21....(array value)NC_000021.9............(new line)NC_000021.9 9824 T C 0.9
Где мы могли легко увидеть
old line
chr1 1243 A T 0.14 chr1 1243 A T 0.14
это NC_000001.11 1243 A T 0.14
происходит потому, что ключ массива (chr1) заменяется значением массива (NC_000001.11), если вы видите вывод, показанный выше для понимания.
Ответ №3:
Похоже, что sub вызывает проблему, и поэтому просто добавьте значение для индекса, указанного в $ 1, к строке с пробелом и выведите строку с короткой рукой 1 и так далее:
awk 'FNR==NR{a[$1]=$2;next} {$0=a[$1]" "$0 }1' lookup.txt file1 > new_table.txt
Комментарии:
1. в чем необходимость изменения всей записи
$0
?2. Мы печатаем 0 долларов за каждую строку с короткой рукой «1» в конце инструкции
3. Однако это не мой вопрос. Почему бы и нет
$1=a[$1]
?4. Поскольку мы не заменяем $ 1 на [$ 1], перед $ 1 ставим [$ 1], а затем пробел. Я предполагаю, что другой был в том, чтобы сделать $ 1 = a [$ 1] » «$ 1