Входной файл, который необходимо отредактировать, выглядит следующим образом (может содержать больше строк):
bundle_id target_id length eff_length tot_counts uniq_counts est_counts eff_counts ambig_distr_alpha ambig_distr_beta fpkm fpkm_conf_low fpkm_conf_high solvable tpm
1 intron_FBgn0035847:4_FBgn0035847:3 61 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
2 intron_FBgn0032515:2_FBgn0032515:4 72 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
3 intron_FBgn0266486:5_FBgn0266486:4 58 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
4 intron_FBgn0031359:10_FBgn0031359:7 4978 1430.739479 91 0 30.333333 105.539363 1.00E+00 1.00E+00 6.30E+00 1.77E+00 1.08E+01 F 1.42E+01
4 intron_FBgn0031359:10_FBgn0031359:8 4978 1430.739479 91 0 30.333333 105.539363 1.00E+00 1.00E+00 6.30E+00 1.77E+00 1.08E+01 F 1.42E+01
4 intron_FBgn0031359:10_FBgn0031359:9 4978 1430.739479 91 0 30.333333 105.539363 1.00E+00 1.00E+00 6.30E+00 1.77E+00 1.08E+01 F 1.42E+01
536 intron_CR31143:1_CR31143:2 40 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
Для каждого идентификатора во 2-м столбцеинтрон_XXXXXXXXX:X_XXXXXXXXX:X, я хочу извлечь строку междуинтрон_и 1-й:(между строкой обычно, но не всегда, начинается с FBgn).
Затем у меня есть следующий список (один столбец дляФБгна другой столбец для соответствующего имени, в которое я хочу преобразовать FBgn):
## FlyBase Gene Mapping Table
## Generated: Fri Dec 20 12:37:29 2013
## Using datasource: dbi:Pg:dbname=fb_2014_01_reporting;host=flysql9;port=5432...
FBgn0035847 mthl7
FBgn0032515 loqs
FBgn0266486 CG45085
FBgn0031359 CG18317
Затем я хочу выполнить поиск извлеченной строки в первом столбце списка.
Если извлеченная строка имеет соответствующее значение во 2-м столбце, я хочу заменить весь идентификаторинтрон_FBgnXXXXXX:X_FBgnXXXXXX:Xс соответствующим именем во 2-м столбце.
Если извлеченная строка не существует в первом столбце, я хочу заменить весь идентификаторинтрон_XXXXXXXXX:X_XXXXXXXXX:Xс извлеченной строкой.
У меня есть следующий сценарий:
ref="gene_map_table_fb_2014_01_short.tsv"
target="HC25_LNv_ZT02_intron_results.txt"
output="temptemp.txt"
declare -A map
while read line
do
if [[ ! -z "$line" ]] && [[ ! "$line" =~ ^#.* ]]
then
key=$(echo "$line" | cut -f 1)
value=$(echo "$line" | cut -f 2)
map[$key]=$value
fi
done < $ref
while read line
do
key=$(echo "$line" | sed -n 's/.*_\([^\.]*\)\:.*/\1/p' | head -1)
if [ ! -z "$key" ]
then
echo "$line" | sed 's/intron_[^[:space:]]*/'${map[$key]}'/g' >> $output
else
echo "$line" | sed 's/intron_[^[:space:]]*/'$key'/g' >> $output
fi
done < $target
Вроде бы все работает нормально, за исключением того, что в выходном файле отсутствуют строки, идентификаторы которых не начинаются с FBgn.
решение1
Ты можешь это сделать:
cat gene_map_table_fb_2014_01_short.tsv |sed '1d' |awk {'print $2'} |awk 'BEGIN{FS=":"} {print $2}' |sed s/._//g
Сначала cat ваш файл, затем удалите первую строку (заголовок столбцов с d1), затем выведите все столбцы, затем разделите 4_FBgn0035847
с помощью awk 'BEGIN{FS=":"} {print $2}'
Затем удалите number_
с помощьюsed s/._//g
Выходные данные:
FBgn0035847
FBgn0032515
FBgn0266486
1FBgn0031359
1FBgn0031359
1FBgn0031359
CR31143
Однако, если у вас лишняя конечная линия и вы хотите ее удалить, вы можете сделать это:
cat gene_map_table_fb_2014_01_short.tsv |sed '1d' |awk {'print $2'} |awk 'BEGIN{FS=":"} {print $2}' |sed s/._//g |sed '$d'
Итак, вывод:
FBgn0035847
FBgn0032515
FBgn0266486
1FBgn0031359
1FBgn0031359
1FBgn0031359
решение2
С использованиемawk
Это создает вывод, разделенный табуляцией:
$ awk -v OFS="\t" 'NR==FNR{a[$1]=$2;next} FNR==1{print;next} {sub(/intron_/, "", $2); sub(/:.*/,"",$2);if ($2 in a) $2=a[$2];print}' gene_map_table_fb_2014_01_short.tsv HC25_LNv_ZT02_intron_results.txt
bundle_id target_id length eff_length tot_counts uniq_counts est_counts eff_counts ambig_distr_alpha ambig_distr_beta fpkm fpkm_conf_low fpkm_conf_high solvable tpm
1 mthl7 61 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
2 loqs 72 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
3 CG45085 58 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
4 CG18317 4978 1430.739479 91 0 30.333333 105.539363 1.00E+00 1.00E+00 6.30E+00 1.77E+00 1.08E+01 F 1.42E+01
4 CG18317 4978 1430.739479 91 0 30.333333 105.539363 1.00E+00 1.00E+00 6.30E+00 1.77E+00 1.08E+01 F 1.42E+01
4 CG18317 4978 1430.739479 91 0 30.333333 105.539363 1.00E+00 1.00E+00 6.30E+00 1.77E+00 1.08E+01 F 1.42E+01
536 CR31143 40 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
Объяснение:
-v OFS="\t"
Это превращает разделитель выходных полей в табуляцию.
NR==FNR{a[$1]=$2;next}
Это создает ассоциативный массив,
a
основанный на первом файле в командной строке, с первым столбцом в качестве ключа и вторым столбцом в качестве значения. Командаnext
указываетawk
пропустить остальные команды и перейти к следующей строке.Файл отображения содержит несколько строк комментариев. Мы могли бы легко добавить дополнительный
if
оператор, чтобы предотвратить их добавление в массивa
. Однако, поскольку они не наносят вреда, мы пропустили это усложнение.FNR==1{print;next}
Это выведет строку заголовка без изменений.
{sub(/intron_/, "", $2); sub(/:.*/,"",$2)
Это удалит лишние данные из второго поля, оставив только нужную нам строку.
`если ($2 в а) $2=а[$2]
Если строка из второго поля присутствует в качестве ключа в массиве
a
, то мы подставляем ее соответствующее значение.print
Исправленная строка печатается.
С использованиемbash
В скрипте замените
if [ ! -z "$key" ]
С:
if [[ "$key" && "${map[$key]}" ]]
Похоже, что скрипту на данном этапе нужно знать, key
присутствует ли в map
или нет. Пересмотренный тест гарантирует не только то, что key
это непустое, но и то, что это в map
.
Сделав это одно изменение, я получаю результат:
$ cat temptemp.txt
bundle_id target_id length eff_length tot_counts uniq_counts est_counts eff_counts ambig_distr_alpha ambig_distr_beta fpkm fpkm_conf_low fpkm_conf_high solvable tpm
1 mthl7 61 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
2 loqs 72 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
3 CG45085 58 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
4 CG18317 4978 1430.739479 91 0 30.333333 105.539363 1.00E+00 1.00E+00 6.30E+00 1.77E+00 1.08E+01 F 1.42E+01
4 CG18317 4978 1430.739479 91 0 30.333333 105.539363 1.00E+00 1.00E+00 6.30E+00 1.77E+00 1.08E+01 F 1.42E+01
4 CG18317 4978 1430.739479 91 0 30.333333 105.539363 1.00E+00 1.00E+00 6.30E+00 1.77E+00 1.08E+01 F 1.42E+01
536 CR31143 40 0 0 0 0 0 0.00E+00 0.00E+00 0.00E+00 0.00E+00 0.00E+00 F 0.00E+00
В качестве отступления от text
, [ ! -z "$key" ]
возвращает true, если key
непустое. Это эквивалентно [ -n "$key" ]
. Поскольку это такой распространенный тест, его можно сократить до [ "$key" ]
. Это можно использовать для упрощения нескольких строк в bash
скрипте.