한 줄의 연속 숫자를 기준으로 .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)의 개수가 연속됨) AND (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 스크립트는 원하는 작업을 수행하지만 sedand 만 사용하지는 않습니다 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. 이로 인해 현재 형태로는 오탐(false positive)이 발생할 수 있습니다. 이는 선과 일치하는 데 사용되는 awk패턴을 향상시키거나 같은 도구를 사용하여 더 잘 수행할 수 있습니다 .grep

관련 정보