파일 a의 첫 번째 열을 파일 b의 단락과 일치시킵니다.

파일 a의 첫 번째 열을 파일 b의 단락과 일치시킵니다.

2개의 파일이 있습니다. 첫 번째는 fileA다음과 같습니다 .

TCONS_00000066  XLOC_000030     -       u       q1:XLOC_000030|TCONS_00000066|0|0.000000|0.000000|0.000000|0.000000|-
TCONS_00000130  XLOC_000057     -       u       q1:XLOC_000057|TCONS_00000130|0|0.000000|0.000000|0.000000|0.000000|-
TCONS_00000395  XLOC_000206     -       u       q1:XLOC_000204|TCONS_00000393|0|0.000000|0.000000|0.000000|0.000000|-

FileB좋다:

>TCONS_00000001 gene=XLOC_000001
AGATGAGCTGGTGGGGATGCTCTAAGAGAACGAGAGAAGCACAGAGCAGATAAACCACACCCACAGGCAC
CACCGTCCTTGTTGGTAATGAAGAAGACGAGACGACGACTTCCCCACTAGGAAACACGACGGAGGCGGAG
ATGATCGACGGCGGAGAGAGCTACAGAAACATCGATGCCTCCTGTCCAATCCCCCCATCCCATTCGGTAG
TTGGATTGAAGACTACCGAATAAGAGAAGCAGGCAGGCAGACAAACCCTTGAACCAAGGAGTCCTCGCTG
AGGAAGCTTTGGATCCACGACGCAGCTATGGCCTCCCCGCCCACCAGGCCGCCAGCCACAACCAGCTGAC
TAGGTCGCATGCATCATCAGATTTCAATCTCCCTTCGTTCCCTGTCCCTAATCCAATACCAATAGGGAGC
AATCAGCTGCTCCTCGACGGCGAGGGAGATGTCGTCGGCCGCGGGCCAAGACAACGGAGATACCGCTGGG
GACTACATCAAGTGGATGTGCGGCGCCGGTGGCCGTGCGGGCGGCGCCATGGCCAACCTCCAGCGCGGCG
TTGGCTCCCTCGTCCGTGACATTGGCGACCCCTGCCTCAACCCATCCCCCGTTAAGGGGAGCAAAATGCT
CAAACCGGAAAAATGGCACACATGTTTTGATAATGATGGAAAGGTCATAGGTTTCCGTAAAGCCCTAAAA
TTCATTGTCTTAGGGGGTGTGGATCCCACTATTCGAGCTGAAGTTTGGGAATTTCTTCTTGGCTGCTATG
CCTTGAGTAGTACCTCAGAGTATAGGAGGAAACTAAGAGCTGTTAGAAGGGAAAAATATCAAATTTTAGT
TAGACAGTGCCAGAGCATGCACCCAAGCATTGGTACAGGTGAGCTTGCTTACGCTGTTGGATCAAAGCTA

이제 첫 번째 열에 fileA는 선택한 성적표 번호와 fileB모든 성적표의 순서가 포함됩니다. fileB첫 번째 열을 스캔 fileA하고 성적표 번호와 함께 일치하는 성적표의 후행 시퀀스를 인쇄하고 싶습니다 .

답변1

sed -n 's|^\(TCONS_[0-9]*\) .*|\
         /^>\1 /,/\\n>/P|p' fileA |
sed -e '$!N' -f - -e D fileB >outfile

...이것은 당신이 원하는 것을 달성할 것입니다. TCONS_문자열과 공백 문자로 시작하는 fileA의 각 줄에 대해 첫 번째 sed줄은 다음과 같은 줄을 인쇄합니다.

/^>TCONS_000001 /,/\n>/P

... 000001선을 생성하는 일련의 숫자는 어디에 있습니까?

두 번째는 sed세 개의 스크립트를 제공합니다. 모두 해당 입력 파일인 fileB에 적용됩니다.

  1. 첫 번째 명령은 마지막 라인을 제외한 패턴 공간의 모든 라인에 ext 입력 라인을 추가 $!N하도록 지시합니다 .N!$

  2. 다음은 stdin입니다. 앞서 언급했듯이 이를 위해 만들어진 -f -첫 번째 항목 입니다.sed

    • 첫 번째는 두 번째의 각 행 sed에 대해 2개의 주소 범위를 인쇄하고, 두 번째는 //,//패턴 공간의 두 주소 사이에 있는 모든 행에 대해 첫 번째 ewline을 sed인쇄하도록 지시합니다.P\n
  3. 마지막 스크립트는 단순히 패턴 공간에서 처음으로 나타나는 ewline을 삭제하고 세 스크립트를 모두 다시 시도하도록 D지시합니다 .sedD\n

결과적으로 sed블록 헤더가 패턴 공간의 선두에 있을 때 두 번째 스크립트의 첫 번째 스크립트와 일치하는 모든 범위가 시작됩니다. ext로 이를 끌어오고 ^이전 라인 이후의 반복을 삭제하며 다음 라인에서 시작됩니다. 닫는 블록 헤더가 먼저 나타나고 여전히 ewline 문자로 구분된 패턴 공간 뒤에 있습니다. 두 번째 것은 해당 구분 기호보다 더 이상 인쇄하지 않기 때문에 fileB를 한 줄 앞으로 이동하여 fileA의 열 1에 있는 문자열로 시작하는 모든 블록을 인쇄하고 다른 것은 인쇄하지 않습니다.ND\nsedPsed


다른(더 복잡하고/더 효율적)방법


세련:

also_fasta()( IFS='
';  get_match_lines(){
        tr   -s  '[:space:]'    \\n  |
        grep "$1" | grep -nFf - "$3"
    }
    get_script(){
        set \\ '\1,$p;n\' '1,\1b\1\' \
               '/^>/!b\1|p' '$c\' q
        sed -n "s|\([^:]*\).*|:\1$*"
    }
    get_match_lines "$@" < "$2"      |
    get_script | sed -nf - "$3"
)

쉘에서 함수를 정의하고 다음과 같이 호출하면:

also_fasta 'TCONS_[0-9]*' fileA fileB

...이제 효과가 있을 것 같아요.

나는 몇 가지 테스트를 한 후에 이것을 알아 냈습니다. 첫 번째는 확실히 작동하지만;느린큰 입력의 경우.

예제의 모든 줄을 [ACGT]*클립보드에 복사한 후 다음과 같은 샘플 데이터를 만들었습니다.

seq -w -s " gene=XLOC_dummy
$(        xsel -bo | sed 's/ *$//')
>TCONS_"  0 512 99999999 >/tmp/temp

seq위의 내용은 다음과 같은 블록을 작성하는 데 사용됩니다 .

>TCONS_99993600 gene=XLOC_dummy
AGATGAGCTGGTGGGGATGCTCTAAGAGAACGAGAGAAGCACAGAGCAGATAAACCACACCCACAGGCAC
CACCGTCCTTGTTGGTAATGAAGAAGACGAGACGACGACTTCCCCACTAGGAAACACGACGGAGGCGGAG
ATGATCGACGGCGGAGAGAGCTACAGAAACATCGATGCCTCCTGTCCAATCCCCCCATCCCATTCGGTAG
TTGGATTGAAGACTACCGAATAAGAGAAGCAGGCAGGCAGACAAACCCTTGAACCAAGGAGTCCTCGCTG
AGGAAGCTTTGGATCCACGACGCAGCTATGGCCTCCCCGCCCACCAGGCCGCCAGCCACAACCAGCTGAC
TAGGTCGCATGCATCATCAGATTTCAATCTCCCTTCGTTCCCTGTCCCTAATCCAATACCAATAGGGAGC
AATCAGCTGCTCCTCGACGGCGAGGGAGATGTCGTCGGCCGCGGGCCAAGACAACGGAGATACCGCTGGG
GACTACATCAAGTGGATGTGCGGCGCCGGTGGCCGTGCGGGCGGCGCCATGGCCAACCTCCAGCGCGGCG
TTGGCTCCCTCGTCCGTGACATTGGCGACCCCTGCCTCAACCCATCCCCCGTTAAGGGGAGCAAAATGCT
CAAACCGGAAAAATGGCACACATGTTTTGATAATGATGGAAAGGTCATAGGTTTCCGTAAAGCCCTAAAA
TTCATTGTCTTAGGGGGTGTGGATCCCACTATTCGAGCTGAAGTTTGGGAATTTCTTCTTGGCTGCTATG
CCTTGAGTAGTACCTCAGAGTATAGGAGGAAACTAAGAGCTGTTAGAAGGGAAAAATATCAAATTTTAGT
TAGACAGTGCCAGAGCATGCACCCAAGCATTGGTACAGGTGAGCTTGCTTACGCTGTTGGATCAAAGCTA

/tmp/temp... 문자열의 숫자 부분이 >TCONS_[0-9]*블록당 512 간격으로 증가하는 파일로 . 전체 파일 크기는 약 185mbs입니다.0000051299999999

그런 다음 나는 다음을 수행했습니다.

grep -F 00\  </tmp/temp | cut -d\> -f2 >/tmp/tempA

...스키마 파일용(이것은 일치 TCONS_[0-9]*00<space>하는 항목으로 선택 범위를 좁힙니다.).

두 파일의 줄 수는 다음과 같습니다.

wc -l /tmp/temp*
  2734369 /tmp/temp
     7813 /tmp/tempA
  2742182 total

해당 크기의 입력에 대해서도 두 개의 s를 실행 하지 않았지만 sed제가 시도한 가장 큰 제안 sed | sed은 데이터 파일, 해당 크기의 십일조 및 선택한 스키마 파일입니다. 2\하지만 그와 비슷합니다.

어쨌든, 무슨 일이 일어나고 있는지 생각해 보니 패턴 파일이 8000개의 정규 표현식에 접근함에 따라 한 줄이 올 때마다 D계속해서 나타나는 이전 정규 표현식을 모두 확인하여 작동해야 한다는 것을 깨달았습니다. 이것은 아마도아니요최선을 다했습니다.

적어도 내가 생성하는 입력에는 나에게 맞는 한 가지가 있습니다. 그것은 다소 연속적입니다. 해당 스레드를 따라가면서 정규식 대신 줄 번호로 작업할 수 있다면 연속적일 필요도 없다는 것을 깨달았습니다 grep. 그래서 .

내가 실행한 명령(그리고 위 기능의 기초)예:

sed  -n 's|^\(TCONS_[0-9]*\) .*|>\1 |p
'    < /tmp/tempA              |
grep -nFf - /tmp/temp          |
sed  -n 's|\([^:]*\):.*|:\1\
        \1,$p;n;1,\1b\1\
        /^>/!b\1|p;$c\' -e q   |
sed  -nf - /tmp/temp

이것을 사용하는 경우 fileBfor /tmp/tempfileAfor 를 교체해야 합니다 /tmp/tempA.

grep -F정규식 대신 고정 문자열을 사용하면 훨씬 빠릅니다.(특히 우리가 1차 경쟁업체와 협력하고 있다는 점을 고려하면)- 나머지는 기본적으로 grep각 결과의 시작 부분에 반환되는 줄 번호를 제외한 모든 결과를 무시합니다. sed중간에 있는 내용은 최종적으로 데이터 파일을 처리하는 프로그램이 한 번이라도 스크립트를 역추적하지 않는 방식으로 출력을 처리합니다. 입력을 처리하는 동안 스크립트 파일을 처리합니다 grep.sed

인쇄된 각 줄의 끝에는 sed다음과 유사한 내용이 기록됩니다.sedgrep

:2732801                     #define branch label :LINENO
2732801,$p                   #if LINENO thru last line print
n                            #overwrite current line w/ next line
1,2732801b2732801            #if first line thru LINENO branch to :LINENO
/^>/!b2732801                #if !not /^>/ branch to :LINENO

따라서 각 grep일치 항목에 대해 sed두 개의 작은 읽기 루프가 구현됩니다 . 첫 번째는 sed현재 줄 번호가 증가되는 grep다음 일치 항목이 나올 때까지 현재 줄을 다음 줄로 덮어쓰는 무작동입니다. 두 번째는 sed현재 줄이 계속해서 인쇄된 다음 줄이 일치할 때까지 다음 줄로 덮어쓰는 인쇄 루프입니다 /^>/. 이러한 방식으로 sed해당 스크립트는 그 안에 있는 파일과 동기적으로 처리됩니다. 즉, 다음 일치하는 줄 번호에 허용되는 것 이상으로 스크립트를 진행하지 않습니다.

이는 다른 스크립트보다 훨씬 더 좋습니다. 그것은 185mbs를 처리합니다 ...

( also_fasta 'TCONS_[0-9]*' /tmp/tempA /tmp/temp; ) \
   3.93s user 0.39s system 100% cpu 4.281 total

...다른 하나는 입력 크기의 10%를 처리합니다...

( sed -n 's|^\(TCONS_[0-9]*\) .*|/>\1 /,/\\n>/P|p' /tmp/tempA  |sed -e  -f... ) \
108.58s user 0.04s system 100% cpu 1:48.56 total

보다 구체적으로 다른 스크립트의 입력 줄 수는 다음과 같습니다.

wc -l /tmp/temp*
  273435 /tmp/temp
     782 /tmp/tempA
  274217 total

답변2

이런 종류의 작업을 자주 수행할 예정이라면 이러한 종류의 작업에 정말 유용한 몇 가지 도구를 사용하는 것이 좋습니다.

  1. FastaToTbl:

    #! /bin/sh
    gawk '{
            if (substr($1,1,1)==">")
            if (NR>1)
                        printf "\n%s\t", substr($0,2,length($0)-1)
            else 
                printf "%s\t", substr($0,2,length($0)-1)
            else 
                    printf "%s", $0
    }END{printf "\n"}'  "$@"
    

    파일을 FastaToTblin 으로 저장 ~/bin하고 실행 가능하게 만듭니다 chmod 755 ~/bin/FastaToTbl.

  2. TblToFasta

    #! /bin/sh
    gawk '{
      sequence=$NF
    
      ls = length(sequence)
      is = 1
      fld  = 1
    
      while (fld < NF)
      {
         if (fld == 1){printf ">"}
         printf "%s " , $fld
          if (fld == NF-1)
          {
            printf "\n"
          }
          fld = fld+1
      }
       while (is <= ls)
      {
        printf "%s\n", substr(sequence,is,60)
        is=is+60
      }
    }' "$@"
    

    파일을 TblToFastain 으로 저장 ~/bin하고 실행 가능하게 만듭니다 chmod 755 ~/bin/TblToFasta.

이제 이 두 스크립트가 설정되었으므로 FastaToTblFASTA 시퀀스를 Tbl 형식(서열 이름, TAB, 시퀀스)으로 변경하여 다음을 사용하여 더 쉽게 검색할 수 있습니다.

FastaToTbl fileB | grep -f <(awk '{print $1}' fileA)  | TblToFasta 

스크립트를 사용하여 FastaToTbl시퀀스와 ID를 동일한 파일에 넣습니다. 검색할 패턴 파일을 요청하는 "file"로 grep에 전달할 수 있는 옵션을 사용하고 있으므로 의 awk '{print $1}' fileA첫 번째 필드를 인쇄합니다 . 마지막으로 FASTA 형식으로 돌아갑니다.fileA<()-fTblToFasta


마지막으로 내 정보를 확인해 보세요.retrieveseqs.pl스크립트는 이 작업과 다른 많은 작업을 수행할 수 있습니다. 예를 들어, 이 경우 다음을 수행할 수 있습니다.

retrieveseqs.pl -f fileB fileA

1이 두 스크립트를 처음 작성한 JF Abril에게 감사드립니다 .

관련 정보