2017-02-09 10 views
0

これを実行する良い方法を見つけようとしましたが、不幸にも私は見つけられませんでした。パターンに基づいてファイル内の繰り返し線を削除します

私はこのフォーマットを持つファイルで働いている:

=クラスタ=
SPEC PRD000681; PRIDE_Exp_Complete_Ac_22491.xml;スペクトル= 1074真
SPEC PRD000681; PRIDE_Exp_Complete_Ac_22498.xml;スペクトル= 2950真

=クラスタ=
SPEC PRD000681; PRIDE_Exp_Complete_Ac_22498.xml;スペクトル= 1876真
SPEC PRD000681; PRIDE_Exp_Complete_Ac_22498.xml;スペクトル= 3479真
SPEC PRD000681; PRIDE_Exp_Complete_Ac_22498.xml;スペクトル= 3785真

=クラスタ=
SPEC PRD000681; PRIDE_Exp_Complete_Ac_22493.xml;スペクトル= 473真
SPEC PRD000681; PRIDE_Exp_Complete_Ac_22493.xml;スペクトル= 473真

ご覧のとおり、すべてのSPEC回線は、文字列スペクトルの番号が繰り返される最後のものを除いて異なります。 私がしたいのは、パターン=Cluster=の間にすべての情報を取り、スペクトル値が繰り返されている行があるかどうかを確認することです。複数の行が繰り返されている場合は、1つを除くすべての行を削除します。

出力ファイルは次のようにすべきである:

=クラスタ=
SPEC PRD000681; PRIDE_Exp_Complete_Ac_22491.xml;スペクトル= 1074真
SPEC PRD000681; PRIDE_Exp_Complete_Ac_22498.xml;スペクトル= 2950真

=クラスタ=
SPEC PRD000681; PRIDE_Exp_Complete_Ac_22498.xml;スペクトル= 1876真
SPEC PRD000681; PRIDE_Exp_Complete_Ac_22498.xml;スペクトル= 3479真
SPEC PRD000681; PRIDE_Exp_Complete_Ac_22498.xml;スペクトル= 3785真

=クラスタ=
SPEC PRD000681; PRIDE_Exp_Complete_Ac_22493.xml;スペクトル= 473、真の私が使用してファイルを分割するために、これを使用してい

パターンが繰り返されているかどうかを確認する方法はわかりません。

#!/usr/bin/perl 

undef $/; 
$_ = <>; 
$n = 0; 

for $match (split(/(?==Cluster=)/)) { 
     open(O, '>temp' . ++$n); 
     print O $match; 
     close(O); 
} 

PD:Perlを使用した方が簡単でしたが、私はPythonも理解しています。

+2

は、連続する重複行はありますか? – Toto

答えて

1

このようなことは、重複する行を(ファイル全体に渡って)削除します。

#!/usr/bin/perl 

use warnings; 
use strict; 

my %seen; 

while (<>) { 
    next if (m/SPEC/ and $seen{$_}++); 
    print; 
} 

あなたが例えば、スペクトル値についてより具体的にしたい場合:

next if (m/spectrum=(\d+)/ and $seen{$1}++); 

あなたのクラスタを分割しているとして、あなたは非常に似て何かを行うことができますが、ちょうど:

if ($line =~ m/==Cluster==/) { 
    open ($output, ">", "temp".$count++); 
    select $output; 
    } 

これは、あなたもあなたのループの外にそれを宣言する必要があります($outputにデフォルト「印刷」の場所を設定します。

あなたもすべき:

  • use strict;use warnings;
  • $_<>を読ん避け、それは不要です。しかし、あなたがしなければならないのであれば、一般的には$block = do { local $/; <> };になります。そして$block =~ m/regex/
  • 使用字句ファイルハンドル:open (my $output, '>', 'filename') or die $!;
  • はオープ​​ンで、あなたのリターンコードをチェックする(or die $!は通常十分です)。

だからのようになります。重複した行が連続している場合、あなたはこのPerl onelinerを使用することができ

#!/usr/bin/perl 

use warnings; 
use strict; 

my %seen; 
my $count = 0; 
my $output; 

while ( <>) { 
    next if (m/spectrum=(\d+)/ and $seen{$1}++); 
    if (m/==Cluster==/) { 
    open ($output, ">", "temp".$count++) or die $!; 
    select $output; 
    } 
    print; 
} 
+0

愚かな質問。セミコロン文字を 'next if'の前に複製してから新しいファイルを生成した後で、セミコロン文字を削除するにはどうすればいいですか?私は '$ str =〜s /; + /;/g;を使うことを考えていましたが、あなたのコードにどのように追加するのか本当に分かりません。 ありがとう! – Enrique

+0

'=〜'を指定しなければ、デフォルトの操作は '$ _'または現在のブロックです。だからあなたが必要とするのは 's /; + /;/g;'です。 – Sobrique

0

perl -ani.back -e 'next if defined($p) && $_ eq $p;$p=$_;print' file.txt 

元のファイルは拡張子.back

とバックアップです
+0

また、['uniq'](https://linux.die.net/man/1/uniq)コマンドを使用してください。 – dolmen

+0

downvotesありがとう!この回答で何が間違っていますか? – Toto

+0

@トートアイデア...私はあなたに1つを与える;) – Enrique

1

このpythonスクリプトでは、私がgroupbyを使用したスクリプトを使用することもできますitertoolsモジュール。

入力ファイルのファイル名がf_input.txt、出力ファイルのファイル名がnew_file.txtとします。

from itertools import groupby 

data = (k.rstrip().split("=Cluster=") for k in open("f_input.txt", 'r')) 
final = list(k for k,_ in groupby(list(data))) 

with open("new_file.txt", 'a') as f: 
    for k in final: 
     if k == ['','']: 
      f.write("=Cluster=\n") 
     elif k == ['']: 
      # write '\n\n' in Windows and '\n' in Linux (tested only in Windows!) 
      f.write("\n\n") 
     else: 
      f.write("{}\n".join(k)) 

出力ファイルnew_file.txtは、希望の出力に似ています。

+0

この作業も同じですが、このスクリプトはSPECも削除します。私はちょうど繰り返された単語を削除するのではなく、繰り返した行を削除したい。 – Enrique

0

タスクは、Perl/Pythonのを必要としないために十分に簡単そうです:隣接する重複行を削除するにはuniqのコマンドを使用します。

$ uniq <input.txt> output.txt 
関連する問題