2011-02-28 58 views
1

我有一些看起來像這樣的數據。它有四條線。每個塊以@字符開頭。使用Sed/AWK/Perl從塊中提取第K行

@SRR037212.1 FC30L5TAA_102708:7:1:741:1355 length=27 
AAAAAAAAAAAAAAAAAAAAAAAAAAA 
+SRR037212.1 FC30L5TAA_102708:7:1:741:1355 length=27 
::::::::::::::::::::::::;;8 
@SRR037212.2 FC30L5TAA_102708:7:1:1045:1765 length=27 
TATAACCAGAAAGTTACAAGTAAACAC 
+SRR037212.2 FC30L5TAA_102708:7:1:1045:1765 length=27 
88888888888888888888888888 

我想要做的是提取每個塊的最後一行。產量:

::::::::::::::::::::::::;;8 
888888888888888888888888888 

注意,塊的最後一行可能包含包括@任何標準的ASCII字符 。

有沒有一個有效的單線程來做到這一點?

回答

4

以下sed命令將打印模式之後的第三行:

sed -n '/^@/{n;n;n;p}' file.txt 
1
$ awk 'BEGIN{RS="@";FS="\n"}{print $4 } ' file 

::::::::::::::::::::::::;;8 
88888888888888888888888888 

如果你總是有這4條線中的一大塊,一些其他的方式

$ ruby -ne 'print if $.%4==0' file 
::::::::::::::::::::::::;;8 
88888888888888888888888888 

$ awk 'NR%4==0' file 
::::::::::::::::::::::::;;8 
88888888888888888888888888 

它還好像你的行總是以「+」開頭的行後面,所以

$ awk '/^\+/{getline;print}' file 
::::::::::::::::::::::::;;8 
88888888888888888888888888 

$ ruby -ne 'gets && print if /^\+/' file 
::::::::::::::::::::::::;;8 
88888888888888888888888888 
+0

當最後一行中有@字符時(特別是OP提到的),第一個awk代碼段不起作用 – bvr 2011-02-28 11:11:07

1

這會打印之前的行,以@開頭,也是最後一行。它可以處理非統一大小的塊,但假定只有一個塊引導行以@開頭。

sed -ne '1d;$p;/^@/!{x;d};/^@/{x;p}' file 

一些解釋是爲了:

  • 首先,你不需要第一行,以便刪除1d
  • 接下來,你總是需要的最後一行,所以打印$p
  • 如果沒有匹配將其交換到保持緩衝區並將其刪除x;d
  • 如果您確實有匹配,將其從保持緩衝區中交換出來,並打印它x;p
4

如果沒有空行:

perl -ne 'print if $. % 4 == 0' file 
+0

這是一個比$更好看。 %4 || print'。 ☺ – tchrist 2011-02-28 14:51:53

+0

但您的解決方案更加明智。 – 2011-02-28 16:17:44

1

這種工作方式類似於羅布麻的回答

awk '/^@/ {mark = NR} NR == mark + 3 {print}' inputfile 

而且,這樣的回答,會不顧工作線的數量每個塊(只要至少有4個)。

的直接模擬到這個問題的答案,但是,這是:

awk '/^@/ {next; next; next; print}' inputfile 
0

這可以用grep容易

grep -A 1 '^@' ./infile 
0

這可能爲你工作(GNU SED)來完成:

sed '/^@/,+2d' file