동일한 텍스트 파일 내에서 다른 줄에 나타나는 여러 비트의 정보를 추출하는 방법


8

동일한 텍스트 파일의 다른 줄에서 발생하는 시퀀스 ID와 클러스터 번호를 추출하려고합니다.

입력은 다음과 같습니다

>Cluster 72
0   319aa, >O311_01007... *
>Cluster 73
0   318aa, >1494_00753... *
1   318aa, >1621_00002... at 99.69%
2   318aa, >1622_00575... at 99.37%
3   318aa, >1633_00422... at 99.37%
4   318aa, >O136_00307... at 99.69%
>Cluster 74
0   318aa, >O139_01028... *
1   318aa, >O142_00961... at 99.69%
>Cluster 75
0   318aa, >O300_00856... *

원하는 출력은 한 열의 시퀀스 ID이고 두 번째 열의 해당 클러스터 번호입니다.

>O311_01007  72
>1494_00753  73
>1621_00002  73
>1622_00575  73
>1633_00422  73
>O136_00307  73
>O139_01028  74
>O142_00961  74
>O300_00856  75

누구든지 이것을 도울 수 있습니까?


시퀀스 ID는 항상 시작하지 않는 행에서 3d 공백으로 구분 된 필드 >입니까? 또한 자매 사이트 Bioinformatics에 관심이 있으실 수도 있습니다 .
terdon

답변:


13

awk로 :

awk -F '[. ]*' 'NF == 2 {id = $2; next} {print $3, id}' input-file
  • 우리는 공백이나 기간에 필드를 나누고 -F '[. ]*'
  • 두 필드의 >Cluster행 ( 행)으로 두 번째 필드를 ID로 저장하고 다음 행으로 이동
  • 다른 줄과 함께 세 번째 필드와 저장된 ID를 인쇄하십시오.

필드 수를 키 오프하는 $1 == ">Cluster"대신 NF == 2파일에 무엇이 있는지에 따라 대신 대신 명시 적으로 찾는 것이 좋습니다 .
Monty Harder

5

awk이것을 위해 사용할 수 있습니다 :

awk '/>Cluster/{
      c=$2;
      next
    }{
      print substr($3,2,length($3)-4), c
    }' file

첫 번째 블록 설명은 클러스터 ID를 캡처하는 것입니다. 두 번째 블록 설명 (기본 설정)은 원하는 데이터를 추출하여 인쇄합니다.


" "대한 인수로 제공 할 필요는 없습니다 print. 쉼표를 사용하여 인수를 구분하면 OFS (기본 공간)를 사용하여 인수를 구분합니다.
muru

4

루비를 하나의 라이너로 사용하는 대안은 다음과 같습니다.

ruby -ne 'case $_; when /^>Cluster (\d+)/;id = $1;when /, (>\w{4}_\w{5})\.\.\./;puts "#{$1} #{id}";end' input_file

또는 여러 줄로 확산 :

ruby -ne 'case $_
when /^>Cluster (\d+)/
  id = $1
when /, (>\w{4}_\w{5})\.\.\./
  puts "#{$1} #{id}"
end' input_file

awkRuby와 regexen을 알고 있다면 버전 보다 읽기 쉽습니다. 보너스 로이 코드는 주변 텍스트를 찾기 때문에 단순히 줄을 나누는 것보다 조금 더 강할 수 있습니다.


1

펄 :

$ perl -ne 'if(/^>.*?(\d+)/){$n=$1;}else{ s/.*(>[^.]+).*/$1 $n/; print}' file 
>O311_01007 72
>1494_00753 73
>1621_00002 73
>1622_00575 73
>1633_00422 73
>O136_00307 73
>O139_01028 74
>O142_00961 74
>O300_00856 75

설명

  • perl -ne: 입력 파일을 한 줄씩 읽고 ( -n) -e각 줄에 지정된 스크립트를 적용하십시오 .
  • if(/^>.*?(\d+)/){$n=$1;}:이 줄이로 시작하는 경우 줄 >끝에서 가장 긴 숫자를 찾아서로 저장하십시오 $n.
  • else{ s/.*(>[^.]+).*/$1 $n/; print: 행이로 시작하지 않으면 ( ) 뒤에 >가장 긴 .문자 가 아닌 가장 긴 길이의 모든 문자를 대체하십시오 . 즉 , 정규식 일치를 캡처 했기 때문에 시퀀스 이름 과의 현재 값입니다 .>>[^.]+$1$n

또는 좀 더 어색한 접근법을 원한다면 :

$ perl -lane 'if($#F==1){$n=$F[1]}else{$F[2]=~s/\.+$//; print "$F[2] $n"}' file 
>O311_01007 72
>1494_00753 73
>1621_00002 73
>1622_00575 73
>1633_00422 73
>O136_00307 73
>O139_01028 74
>O142_00961 74
>O300_00856 75

이것은 다양한 awk접근 방식 과 동일한 기본 아이디어를 수행하는 약간 더 성가신 방법입니다 . 나는 완성을 위해 그리고 Perl 팬들을 위해 그것을 포함시키고 있습니다. 설명이 필요하면 awk 솔루션을 사용하십시오 :).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.