Фильтрация файла .CSV на основе последовательных чисел в строке

Фильтрация файла .CSV на основе последовательных чисел в строке

У меня есть CSV-файл следующего вида:

                 1st       2nd      3rd       4th
   ID      ...   Res       Res      Res       Res        (other columns) ...

RZ_AUTO_1, 1cx0, C118, B, C119, B, A165, B, A166, B, CC/AA Canonical ribose-zipper
RZ_AUTO_2, 1drz, C118, B, C119, B, A165, B, A166, B, CC/AA Canonical ribose-zipper
RZ_AUTO_3, 1ffk, C208, 0, G209, 0, A665, 0, A666, 0, CG/AA Canonical ribose-zipper
RZ_AUTO_4, 1ffk, C2767, 0, C2682, 0, G2679, 0, A2681, 0, CC/GA Naked ribose-zipper
RZ_AUTO_5, 1ffk, G2574, 0, C2575, 0, G2798, 0, A2776, 0, GC/GA Single ribose-zipper

Я хотел бы извлечь строки, где (число First_Residue (третье поле) и Second_Residue ($5) являются последовательными) И (число Third_Residue ($7) и Fourth_Residue ($9) являются последовательными). Пример вывода будет таким:

RZ_AUTO_1, 1cx0, C118, B, C119, B, A165, B, A166, B, CC/AA Canonical ribose-zipper
RZ_AUTO_2, 1drz, C118, B, C119, B, A165, B, A166, B, CC/AA Canonical ribose-zipper
RZ_AUTO_3, 1ffk, C208, 0, G209, 0, A665, 0, A666, 0, CG/AA Canonical ribose-zipper

Строки 4 и 5 будут удалены, поскольку номера остатков не являются последовательными.

Как это сделать с помощью awk или sed?

решение1

Если каждое из сравниваемых полей имеет один нечисловой префиксный символ ( Cили Aв вашем примере), то вы должны иметь возможность извлекать и сравнивать числовые подстроки непосредственно в awk, например

$ awk -F"[ \t,]+" 'substr($5,2)+0==substr($3,2)+1 && substr($9,2)+0==substr($7,2)+1' file.csv
RZ_AUTO_1, 1cx0, C118, B, C119, B, A165, B, A166, B, CC/AA Canonical ribose-zipper 
RZ_AUTO_2, 1drz, C118, B, C119, B, A165, B, A166, B, CC/AA Canonical ribose-zipper 
RZ_AUTO_3, 1ffk, C208, 0, G209, 0, A665, 0, A666, 0, CG/AA Canonical ribose-zipper

решение2

Если вы можете использовать perl:

$ perl -F, -anle '
    map { s/\D//g } @F;
    print if ++$F[2] == $F[4] and ++$F[6] == $F[8];
' file
RZ_AUTO_1, 1cx0, C118, B, C119, B, A165, B, A166, B, CC/AA Canonical ribose-zipper
RZ_AUTO_2, 1drz, C118, B, C119, B, A165, B, A166, B, CC/AA Canonical ribose-zipper
RZ_AUTO_3, 1ffk, C208, 0, G209, 0, A665, 0, A666, 0, CG/AA Canonical ribose-zipper

решение3

Этот скрипт Bash делает то, что вам нужно, но не использует только sedи awk. Я уверен, что если бы на его разработку было потрачено больше времени, его можно было бы усовершенствовать, но он, в общем-то, делает то, что вам нужно.

$ more cmd.bash 
#!/bin/bash

while read line; do 
    f1=$(echo "$line" | awk -F", " '{print $3}')
    f2=$(echo "$line" | awk -F", " '{print $7}')
    echo "$line" | grep  "${f1}.*$(expr ${f1:2} + 1).*${f2}.*$(expr ${f2:2} + 1)"
done <file

Пример запуска

$ ./cmd.bash 
RZ_AUTO_1, 1cx0, C118, B, C119, B, A165, B, A166, B, CC/AA Canonical ribose-zipper
RZ_AUTO_2, 1drz, C118, B, C119, B, A165, B, A166, B, CC/AA Canonical ribose-zipper
RZ_AUTO_3, 1ffk, C208, 0, G209, 0, A665, 0, A666, 0, CG/AA Canonical ribose-zipper

Недостатки

Одной из областей, где необходимо дальнейшее улучшение, является выбор совпадений в grepстроке. Это может привести к ложным срабатываниям в его текущей форме. Это можно сделать лучше, используя такой инструмент, как awkили улучшив шаблон, который grepиспользуется для сопоставления строк.

Связанный контент