#awk
Вопрос:
У меня есть два файла.
Файл 1 (сокращенный):
1 1:135982[b38]A,G 0 12500 A G
1 1:611317[b38]A,G 0 611317 A G
1 1:722408[b38]G,C 0 722408 G C
1 1:726649[b38]G,A 0 726649 G A
Файл 2 (сокращенный):
ENSG00000223972 ENST00000456328 DDX11L1 1 11869 14409
ENSG00000223972 ENST00000450305 DDX11L1 1 11869 14409
ENSG00000227232 ENST00000488147 WASH7P 1 14404 29570
Я хочу создать новый файл, в котором:
- если столбец 1 в файле 1 соответствует столбцу 4 файла 2
- И столбец 4 файла 1 находится в диапазоне столбцов 5 и 6 файла 2
Распечатайте столбец 3 файла 2 и столбец 2 файла 1.
Пример:
Для первой строки файла 1 столбец 1 (1) соответствует столбцу 4 файла 2 (также 1), А столбец 4 файла 1 (12500) равен >= 11869 и >:
DDX11L1 1:134982[b38]A,G
В этом примере других совпадений не существует, так что это был бы единственный результат.
Как я могу сделать это с помощью awk?
Комментарии:
1. Насколько велики файлы? Они отсортированы? Вы смотрите на время выполнения O(m*n) и потенциально значительное использование памяти, если вы не можете оптимизировать. Такого рода вещи тривиально реализуются в виде sql-запроса (sqlite может читать csv-файлы).
2. Не думал об этом. Да, это невозможно, файлы довольно большие. Сразу подумал о SQL как о первом ресурсе, но хотел знать, есть ли решение awk.
3. Я думаю, что с awk вам придется либо хранить весь один файл в памяти, либо перечитывать его снова и снова. Вероятно, довольно медленно, если это не укладывается в память. SQL может быть достаточно быстрым без изменений; если нет, создание явных индексов может ускорить процесс.
Ответ №1:
Не awk, но тривиально с sqlite:
#!/bin/bash
# convert spaces to tabs
tr -s ' t' 't' <file1.raw >file1.tsv
tr -s ' t' 't' <file2.raw >file2.tsv
sqlite3 >output.tsv <<'EOD'
create table t1 (c1,c2,c3,c4 int,c5,c6);
create table t2 (c1,c2,c3,c4,c5 int,c6 int);
.mode tabs
.import file1.tsv t1
.import file2.tsv t2
select distinct t2.c3, t1.c2 from t1,t2
where t1.c1=t2.c4 and t1.c4 between t2.c5 and t2.c6;
EOD
Комментарии:
1. Это не работает. Например, первая строка вывода
DDX11L1 1:135982[b38]A,G
. 135982 не находится между 11869 и 14409. Он также размещает то же1:135982[b38]A,G
самое с другими строками из другого файла, которые также имеют совершенно другие координаты. Для контекста DDX11L1-это ген, который охватывает определенное пространство, а другое дело-мутация, которая находится только в одном месте. Не может быть присвоено более чем одному гену.2. Я изменил сценарий, чтобы привести числовые столбцы в виде целых чисел, и, похоже, теперь он работает.