Eu tenho um arquivo CSV da seguinte forma:
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
O que eu gostaria de fazer é extrair linhas onde (o número de First_Residue (o terceiro campo) e Second_Residue ($ 5) são consecutivos) E (o número de Third_Residue ($ 7) e Fourth_Residue ($ 9) são consecutivos). Um exemplo de saída seria assim:
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
As linhas 4 e 5 serão removidas porque os números dos resíduos não são consecutivos.
Como posso fazer isso usando awk ou sed?
Responder1
Se cada um dos campos a serem comparados tiver um único caractere de prefixo não numérico ( C
ou A
no seu exemplo), você poderá extrair e comparar as substrings numéricas diretamente no awk, por exemplo
$ 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
Responder2
Se você puder usar 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
Responder3
Este script Bash faz o que você deseja, mas não usa apenas sed
e awk
. Tenho certeza de que se gastasse mais tempo desenvolvendo isso, ele poderia ser ainda mais refinado, mas, grosso modo, faz o que você deseja.
$ 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
Exemplo de execução
$ ./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
Fraquezas
Uma área onde precisa ser melhorada é na seleção das partidas na grep
linha. Isso pode levar a falsos positivos na forma atual. Isso pode ser feito melhor usando uma ferramenta como essa awk
ou aprimorando o padrão grep
usado para combinar com as linhas.