วิธีดึงข้อมูลหลายบิตที่ปรากฏบนบรรทัดต่าง ๆ ภายในไฟล์ข้อความเดียวกัน


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

มีใครสามารถช่วยได้บ้าง


รหัสลำดับจะเป็นฟิลด์ 3 มิติที่คั่นด้วยช่องว่างบนบรรทัดที่ไม่ได้เริ่มต้นด้วย>หรือไม่ นอกจากนี้คุณอาจจะสนใจในเว็บไซต์น้องสาวของเราชีวสารสนเทศศาสตร์
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 ในฐานะหนึ่งซับ:

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

ฉันเดาว่ามันอ่านได้ง่ายกว่าawkเวอร์ชั่นหากคุณรู้จัก Ruby และ regexen เป็นโบนัสโค้ดนี้อาจมีความทนทานกว่าการแยกบรรทัดเพียงเล็กน้อยเนื่องจากมองหาข้อความโดยรอบ


1

Perl:

$ 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เพราะเราได้บันทึกการแข่งขัน regex) $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.