파일에서 길이가 다른 두 개의 연속 라인을 구문 분석하는 스크립트

파일에서 길이가 다른 두 개의 연속 라인을 구문 분석하는 스크립트

연속되는 두 줄의 길이가 모두 같은(텍스트가 완전히 다른) 대용량 파일을 구문 분석하려고 합니다. 검색해봤는데 첫글이 여기에 있네요. 스크립트를 찾아서 수정해 보았으나 재미가 없었습니다. file은 정렬 출력 파일입니다. 시퀀스와 품질 점수를 분석하여 파일은 다음과 같습니다.

CCTCGNAACCCAAAAACTTTGATTTCTNATAAGGTGCCAGCGGAGTCCTAAAAGCAACATCCGCTGATCCCTGGT
AAAAA#EEEEEEEEEEEEEEEEEEEEE#EEEEEEEEAEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
CCCCANCCAAACTCCCCACCTGACAATNTCCTCCGCCCGGATCGACCCGCCGAAGCGAGTCTTGGGTCTAAA
AAAAA#EEEEEEEEEEEAEEEEEEEEE#EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
ATCGTNTATGGTTGAGACTAGGACGGTNTCTGATCGTCTTCGAGCCCCCAACTTTCGTTCTTGATTAATGAAAAC
AAAAA#EEEEEEEEEEEEEEEEEEEEE#EEEEEEEEEEEEAEEEEEEAEEEAEEEEEEEEEEEEEEEEEEEEEEE
CCCACNTGGAGCTCTCGATTCCGTGGGNTGGCTCAACAAAGCAGCCACCCCGTCCTACCTATTTAAAGTTTG
AAAAA#EEEEEEEEEEEEEEEEEEEEE#EEEEEEEEEEEEEEEEEEAEEEEEEEEEEEEEEEEEEEEEEEEE
GCATCNTTTATGGTTGAGACTAGGACGNTATCTGATCGTCTTCGAGCCCCCAACTTTCGTTCTTGATTAATGAA
6AAAA#EEEEEAAAEEEEEEAEEAEEE#EEEEEEEAEAEEEEAEEAAA/EAEEEEAEEAEEAEEAEAAEEEEEE

질문: 각 시퀀스 베이스에 해당 점수가 없는 손상된 라인 쌍이 있습니다. 즉, 각 쌍의 두 라인 길이가 동일해야 합니다. 잘못된 라인 쌍을 어떻게 구문 분석합니까? 파일에는 1억 줄이 있습니다.

나는 parser.sh라는 코드를 시도했습니다.

{ curr = $0 }
(NR%2)==0 {
    currLgth = length(curr)
    prevLgth = length(prev)
    maxLgth = (currLgth > prevLgth ? currLgth : prevLgth)
    if (prevLgth==currLgth) {
        print ""
        print prevLgth
        print currLgth
        for (i=1; i<=maxLgth; i++) {
        }
    }
}
{ prev = curr }

실행되지만 awk -f parser.sh filename "같지 않음"('==')을 사용하더라도 모든 줄 길이가 인쇄됩니다.

75
75

72
72

75
75

72
72

저는 코더가 아니므로 미리 사과드리며 도움이 필요합니다. 일반적으로 코드를 찾아 수정하여 작동하게 만드는 것이 가능하지만 이 경우에는 그렇지 않습니다. -피

Fastq 파일은 한 번에 4줄을 읽습니다. Read#1 e,g에는 다음 4줄이 포함됩니다.

@sample1
CGGCATCGTTTATGGTTGAGACTAGGACG
+
AAAAAEEEEEEEEEEEEEEEEEEEEEEEE

첫 번째 줄은 샘플 이름이고, 두 번째 줄은 실제 시퀀스이고, 세 번째 줄은 "+" 기호이고, 네 번째 줄은 시퀀스의 각 염기에 대한 ASCII "점수" 세트입니다. 베이스당 하나의 점수만 있으므로 라인 2의 길이는 라인 4의 길이와 같아야 합니다. 저는 2행과 4행을 분석하여 길이가 다른 쌍을 찾았습니다. 대신 페어링이 누락된 것처럼 보이는 결과가 나타납니다.

다음은 물음표가 누락되거나 해결되지 않은 품질 점수를 나타내는 FASTQ 파일의 예입니다.

@sample1
CGGCATCGTTTATGGTTGAGACTAGGACG
+
AAAAAEEEEEEEEEEEEEEEEEEEEEEEE
@sample2
CCGGCTTCCGGTTCATCCCGCATCGCCAGTTC
+
@sample3
AAAA6E6/EEEEEEEE6/EE/EEAEEAA//E/
+
@sample4
ATTTCGGGGGGGGGGGGGG
+
??????????????????????????????????
@Sample5
GGTTAGCGCGCAGTTGGGCACCGTAACCCGGCTT
+
AAAAAEEEEEAEEEEEEEEEEEEEEEEEE//<EE
@sample6
CTAACCTGTCTCACGACGGTCTAAACCCAGCTCA
+
AAAAAEEEEEEEEEEEEEEEEEEEEEEEEEEEEE

이것은 내 (라인 2 + 4) 구문 분석된 파일의 모습입니다:

CGGCATCGTTTATGGTTGAGACTAGGACG
AAAAAEEEEEEEEEEEEEEEEEEEEEEEE
CCGGCTTCCGGTTCATCCCGCATCGCCAGTTC
AAAA6E6/EEEEEEEE6/EE/EEAEEAA//E/
ATTTCGGGGGGGGGGGGGG
GGTTAGCGCGCAGTTGGGCACCGTAACCCGGCTT
AAAAAEEEEEAEEEEEEEEEEEEEEEEEE//<EE
CTAACCTGTCTCACGACGGTCTAAACCCAGCTCA
AAAAAEEEEEEEEEEEEEEEEEEEEEEEEEEEEE

사이에 품질 점수 선이 없는 두 개의 연속 시퀀스 행이 있습니다.

ATTTCGGGGGGGGGGGGGG
GGTTAGCGCGCAGTTGGGCACCGTAACCCGGCTT

당신이 나에게 준 코드를 사용하여 :

awk 'NR%2==0 && length($0)!=last{print "Bad pair at lines",NR-1,"and",NR}{last=length($0)}' Fastq-seq-qual-parsed.txt
Bad pair at lines 5 and 6

또는: ./new-try.awk

답변1

내가 제안 할게

awk '
    { first = $0; getline; second = $0 }
    length(first) != length(second) {
        print "Error at line", NR-1
        print first
        print second
    }
' file

일반 bash를 사용할 수도 있지만 속도가 훨씬 느려집니다.

nr=1
while IFS= read -r first; IFS= read -r second; do 
    if (( ${#first} != ${#second} )); then 
        printf "%s\n" "problem at line $nr" "$first" "$second"
    fi
    ((nr+=2))
done < file

답변2

노력하다:

awk 'NR%2==0 && length($0)!=last{print "Bad pair at lines",NR-1,"and",NR} {last=length($0)}' file

이것을 테스트 파일로 사용해 보겠습니다.

$ cat file
good123
good345
bad12
bad123
good_again
good_also1

명령을 사용하면 일치하지 않는 쌍이 올바르게 식별됩니다.

$ awk 'NR%2==0 && length($0)!=last{print "Bad pair at lines",NR-1,"and",NR} {last=length($0)}' file
Bad pair at lines 3 and 4

어떻게 작동하나요?

  • NR%2==0 && length($0)!=last{print "Bad pair at lines",NR-1,"and",NR}

    짝수 행에 있을 때 NR%2==0해당 행의 길이가 이전 행과 같은지 확인합니다. 그렇지 않은 경우 length($0)!=last메시지를 인쇄합니다.

  • last=length($0)

    이렇게 하면 현재 줄의 길이가 변수에 저장됩니다 last.

여러 줄 버전

코드를 여러 줄에 걸쳐 분산시키려는 경우:

awk '
    NR%2==0 && length($0)!=last {
        print "Bad pair at lines",NR-1,"and",NR
    }

    {
        last=length($0)
    }' file

파일의 특정 줄을 인쇄하는 방법

예를 들어, 파일의 3행을 인쇄하려면 다음을 사용할 수 있습니다.

$ awk 'NR==3' file
bad12

범위를 인쇄하려면 3부터 6까지의 모든 줄을 인쇄하려면 다음을 사용할 수 있습니다.

$ awk 'NR>=3 && NR<=6' file
bad12
bad123
good_again
good_also1

또는 sed를 사용하여 유사한 결과를 얻을 수 있습니다.

$ sed -n '3p' file
bad12
$ sed -n '3,6p' file
bad12
bad123
good_again
good_also1

필터링되지 않은 입력 데이터 사용

다음 입력 파일을 고려하십시오.

$ cat File
@sample1
CGGCATCGTTTATGGTTGAGACTAGGACG
+
AAAAAEEEEEEEEEEEEEEEEEEEEEEEE
@sample2
CCGGCTTCCGGTTCATCCCGCATCGCCAGTTC
+
@sample3
AAAA6E6/EEEEEEEE6/EE/EEAEEAA//E/
+
@sample4
ATTTCGGGGGGGGGGGGGG
+
??????????????????????????????????
@Sample5
GGTTAGCGCGCAGTTGGGCACCGTAACCCGGCTT
+
AAAAAEEEEEAEEEEEEEEEEEEEEEEEE//<EE
@sample6
CTAACCTGTCTCACGACGGTCTAAACCCAGCTCA
+
AAAAAEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
@sample7
CTAACCTGTCTCACGACGGTCTAAACCCAGCTCA
+
AAAAAEEEEEEEEEEEEEEEEEEEEEEEEEEEE

?다음과 같이 잘못된 샘플, 즉 길이가 다른 줄이 있거나 두 번째 줄로 시작하는 샘플을 감지할 수 있습니다 .

$ awk '/^\+/{next} /^@/{s=$0;n=NR;next} prev{if(/^\?/ || length(prev)!=length($0)) printf "Sample %s (line %s) is bad:\n%s\n%s\n",s,n,prev,$0;prev="";next} {prev=$0}' File
Sample @sample4 (line 11) is bad:
ATTTCGGGGGGGGGGGGGG
??????????????????????????????????
Sample @sample7 (line 23) is bad:
CTAACCTGTCTCACGACGGTCTAAACCCAGCTCA
AAAAAEEEEEEEEEEEEEEEEEEEEEEEEEEEE

또는 두 번째 줄("quality")이 다음으로 시작하는 샘플을 무시하려는 경우 ?:

$ awk '/^\+/{next} /^@/{s=$0;n=NR;next} prev{if(!/^\?/ && length(prev)!=length($0)) printf "Sample %s (line %s) is bad:\n%s\n%s\n",s,n,prev,$0;prev="";next} {prev=$0}' File
Sample @sample7 (line 23) is bad:
CTAACCTGTCTCACGACGGTCTAAACCCAGCTCA
AAAAAEEEEEEEEEEEEEEEEEEEEEEEEEEEE

답변3

먼저 뭔가를 찾을 수 있도록 5행과 6행의 길이가 같지 않은 테스트 파일을 만듭니다("cccccc" 다음과 같은):

printf '%s\n' aaa aaa bbbb bbbb cccc ccc ddd ddd > foo

추상적인부자두 개의 가상 파일로 분할하여 사용bash 프로세스 교체sed, 여기서 각 문자는 다음으로 대체됩니다 ..

  • 이것첫 번째가상 파일은 실제 파일을 추상화합니다.
  • 이것2위가상 파일은 추상적일 뿐입니다.이상한한 줄을 복사한 다음 복사하세요.2위연속적으로 변환이상한그리고심지어선의 길이는 같습니다.

... diff다음 파일은 다음과 같습니다.

diff <(sed 's/././g' foo) <(sed -n '1~2{s/././g;p;p}' foo)

출력에는 6행이 일치하지 않는 것으로 표시됩니다.

6c6
< ...
---
> ....

위의 출력이 너무 장황하다면 diff유사한 프로그램에 많은 옵션이 있거나 필요에 따라 필터링될 수 있습니다. 줄 번호만 표시:

diff <(sed 's/././g' foo) <(sed -n '1~2{s/././g;p;p}' foo) | 
sed -n 's/c.*//p'

산출:

6

아니면 좀 더 자세히 말하자면,숫자가 일치하지 않는 원본 파일 줄:

f=foo
diff <(sed 's/././g' $f) <(sed -n '1~2{s/././g;p;p}' $f) |  
sed -n 's/^\(.*\)c.*/\1/p' | grep -B 1 -wf - <(cat -n $f)

산출:

     5  cccc
     6  ccc

관련 정보