2016-02-23 24 views
2

如何刪除行中的其他行的子行,同時保留包含它們的較長字符串?刪除其他行的子字符串的行

我有一個包含肽序列作爲字符串的文件 - 每行一個序列字符串。我想保留包含所有序列的字符串,並刪除文件中其他行的子字符串的所有行。

輸入

GSAAQQYW 
ATFYGGSDASGT 
GSAAQQYWTPANATFYGGSDASGT 
GSAAQQYWTPANATF 
ATFYGGSDASGT 
NYARTTCRRTG 
IVPVNYARTTCRRTGGIRFTITGHDYFDN 
RFTITGHDYFDN 
IVPVNYARTTCRRTG 
ARTTCRRTGGIRFTITG 

期望輸出

GSAAQQYWTPANATFYGGSDASGT 
IVPVNYARTTCRRTGGIRFTITGHDYFDN 

輸出應該只保留最長的字符串,刪除這是最長的字符串的子行。因此,在上面的輸入中,行1,2,4和5是行3的子字符串,因此輸出保留行3.類似地,行6,8,9和10上的行都是行7的子行,因此行7被保留並寫入輸出。

+0

什麼是「長「? 「兩個最長」? –

+0

啊,你想刪除任何字符串是另一個字符串的子字符串嗎?你到目前爲止嘗試過什麼? –

+0

https://www.gnu.org/software/gawk/manual/html_node/String-Functions.html#index-index_0028_0029-function – user3159253

回答

2

這應該做你想要什麼:

$ cat tst.awk 
{ arr[$0]; strs=strs $0 RS } 
END { 
    for (str in arr) { 
     if (split(strs,tmp,str) == 2) { 
      print str 
     } 
    } 
} 

$ awk -f tst.awk file 
IVPVNYARTTCRRTGGIRFTITGHDYFDN 
GSAAQQYWTPANATFYGGSDASGT 

它循環通過arr中的每個字符串然後使用它作爲split()的分隔符值 - 如果字符串出現一次,那麼完整的文件內容將被分割成一半,因此split()將返回2,但如果字符串是其他字符串的子集,那麼文件內容將被拆分成多個段,因此拆分會返回一些高於2的數字。

如果一個字符串可能在輸入中出現多次,並且您希望它在輸出中多次打印(請參閱註釋中的問題@ G.Cito下文),那麼你會修改上面:

!cnt[$0]++ { strs=strs $0 RS } 
END { 
    for (str in cnt) { 
     if (split(strs,tmp,str) == 2) { 
      for (i=1;i<=cnt[str];i++) { 
       print str 
      } 
     } 
    } 
} 
+0

工作得很好!你能解釋一下循環嗎? –

+1

我在底部添加了一個解釋 –

+0

@EdMorton所以'file'中的所有字符串,'awk'只找到並打印可以分成兩部分的字符串(跳過那些不能被分割或分割多次的字符串) 。 ++不錯,簡單!是否有一種簡單的方法來處理「長」字符串(我稱之爲下面更多巴洛克式perl解決方案中的「主字符串」)多次出現的情況?使用'awk'腳本和perl'%uniq'散列,它會被排除在輸出之外。 –

3

可能:

input=./input_file 
while read -r str 
do 
[[ $(grep -c "$str" "$input") == 1 ]] && echo $str 
done < "$input" 

生產:

GSAAQQYWTPANATFYGGSDASGT 
IVPVNYARTTCRRTGGIRFTITGHDYFDN 

它是緩慢的 - 但是簡單..

+2

謝謝,這工作 –

-1

這將幫助你什麼你到底需要:

awk'{打印長度(),NR,$ 0 | 「sort -rn」}'sed_longer.txt |頭-n 2

0

作爲一個Perl的 「一個班輪」(這應該剪切和粘貼到終端工作):

perl -E 'chomp(@r=<>); 
     for $i (0..$#r){ 
      map { $uniq{$_}++ if (index($r[$i], $_) != -1) } @r; 
     } 
     for (sort keys %uniq){ say if ($uniq{$_} == 1); }' peptide_seq.txt 
  • 我們讀詩的Chomp從標準輸入文件(peptide_seq.txt)( <>)並將其保存在@r中,該數組中的每個元素都是文件中每行的字符串。

  • 接下來我們通過陣列和@rmap的元素的哈希(%uniq),其中每個key是每行的內容迭代;並且每個value是一個數字,當一行被發現是另一行的子字符串時,該數字就會增加。使用index我們可以check whether a string contains a sub-string並遞增相應的散列值ifindex()不會返回「找不到」的值(-1)。

  • 「主」字符串包含所有其他的字符串作爲自己的子串和僅會被遞增,因此,我們循環再打印%uniq哈希具有價值== 1的鑰匙。這第二個循環可能是map代替:

    map { say if ($uniq{$_} == 1) } sort keys uniq ;

作爲一個獨立的腳本,可能是:

#!perl -l 
chomp(@r=<DATA>); 

for $i (0..$#r) { 
    map { $uniq{$_}++ if (index($r[$i], $_) != -1) } @r ; 
} 

map { print if ($uniq{$_} == 1) } sort keys %uniq ; 

__DATA__ 
GSAAQQYW 
ATFYGGSDASGT 
GSAAQQYWTPANATFYGGSDASGT 
GSAAQQYWTPANATF 
ATFYGGSDASGT 
NYARTTCRRTG 
IVPVNYARTTCRRTGGIRFTITGHDYFDN 
RFTITGHDYFDN 
IVPVNYARTTCRRTG 
ARTTCRRTGGIRFTITG 

輸出

GSAAQQYWTPANATFYGGSDASGT 
IVPVNYARTTCRRTGGIRFTITGHDYFDN 
相關問題