Отображать только строки, в которых 1 столбец равен другому, а второй столбец находится в диапазоне в AWK и Bash

У меня есть два файла. Первый файл выглядит так:

1 174392 
1 230402
2 4933400
3 39322
4 42390021
5 80022392
6 3818110

и так далее

второй файл выглядит так:

chr1 23987 137011
chr1 220320 439292
chr2 220320 439292
chr2 2389328 3293292
chr3 392329 398191
chr4 421212 3292393

и так далее.

Я хочу вернуть всю строку, при условии, что первый столбец в ФАЙЛЕ1 = первая строка в ФАЙЛЕ2, поскольку совпадение строки И второй столбец в файле 2 больше, чем столбец 2 в ФАЙЛЕ2, но меньше, чем столбец 3 в ФАЙЛЕ2.

Таким образом, в приведенном выше примере строка 1 230402
в ФАЙЛЕ1 и chr1 220320 439292 в ФАЙЛЕ2 будут удовлетворять условиям, поскольку 230402 находится между 220320 и 439292, а 1 будет равна chr1 после того, как я сопоставлю строки, поэтому эта строка в ФАЙЛ2 будет напечатан.

Код, который я написал, был таким:

#!/bin/bash

$F1="FILE1.txt"

read COL1 COL2
do
    grep -w "chr$COL1" FILE2.tsv \
    | awk -v C2=$COL2 '{if (C2>$1 && C2<$2); print $0}'
done < "$F1"

Я пробовал много вариантов этого. Меня не волнует, полностью ли код написан на awk, полностью на bash или на смеси.

Кто-нибудь может помочь?

Благодарю вас!


person Vincent Laufer    schedule 23.05.2014    source источник
comment
Я полагаю, вы имели в виду the first column in FILE1 = the first column in FILE2 и the 2nd column in FILE1 is greater than column 2 in FILE2?   -  person Etan Reisner    schedule 23.05.2014


Ответы (3)


Вот один из способов использования awk:

awk '
NR==FNR {
    $1 = "chr" $1
    seq[$1,$2]++;
    next
}
{
    for(key in seq) {
        split(key, tmp, SUBSEP); 
        if(tmp[1] == $1 && $2 <= tmp[2] && tmp[2] <= $3 ) {
            print $0
        }
    }
}' file1 file2
chr1 220320 439292
  • Мы читаем первый файл в массив, используя ключ в качестве столбцов 1 и 2. Мы добавляем строку «chr» в столбец 1, делая ее ключом для удобства сравнения позже.
  • Когда мы обрабатываем файл 2, мы перебираем наш массив и разделяем ключ.
  • Мы сравниваем первую часть нашего ключа со столбцом 1 и проверяем, находится ли вторая часть ключа в диапазоне второго и третьего столбцов.
  • Если он удовлетворяет нашему условию, мы печатаем строку.
person jaypal singh    schedule 23.05.2014

awk 'BEGIN {i = 0}
     FNR == NR { chr[i] = "chr" $1; test[i++] = $2 }
     FNR < NR { for (c in chr) {
                if ($1 == chr[c] && test[c] > $2 && test[c] < $3) { print }
            }
        }' FILE1.txt FILE2.tsv

FNR — это номер строки в текущем файле, NR — это номер строки во всех входных данных. Итак, первый блок обрабатывает первый файл, собирая все строки в массивы. Второй блок обрабатывает все оставшиеся файлы, просматривая массив значений chrN в поисках соответствия и сравнивая два других числа с числом из первого файла.

person Barmar    schedule 23.05.2014
comment
Я не уверен, что это действительно проблема, awk автоматически инициализирует переменные в "" при первом использовании. Но я добавил явную 0 инициализацию. - person Barmar; 23.05.2014
comment
Судя по всему, вы правы, я попробовал оригинальный скрипт с перестановкой строк, и он не удался. Но обновленный скрипт работает. Спасибо - person Barmar; 23.05.2014
comment
Я думал, что нулевая строка будет допустимым индексом массива в хеше. - person Barmar; 23.05.2014
comment
Я использовал постинкремент, поэтому он увеличивается после сохранения столбца2. - person Barmar; 23.05.2014
comment
Ааа, понял — поскольку ++ является числовым оператором, он возвращает исходное значение, преобразованное в число, а не необработанное исходное значение. - person Barmar; 23.05.2014
comment
Да, извините, я не очень ясно объяснил. Я продолжу и удалю свои комментарии, поскольку они загромождают ваш ответ. :). - person jaypal singh; 23.05.2014

Спасибо большое!

Эти ответы работают и очень полезны.

Также, наконец, я понял, что должен был иметь:

awk -v C2=$COL2 'if (C2>$1 && C2<$2); {print $0}'

с скобой в другом месте, и я был бы в порядке.

В любом случае большое спасибо!

person Vincent Laufer    schedule 23.05.2014