0

失敗する Ruby の正規表現について助けが必要です。理由がわかりませんでした。Ruby を使用して、次の構造を持つ大規模なバイオ データベースからテキストの一部を取得しています (簡単にするために 2 つの項目のみを示します)。

//
ID   IPI00303292.1         IPI;      PRT;   538 AA.
AC   IPI00303292;
DR   Superfamily; SSF48371; ARM; 1.
DR   UniProt/Swiss-Prot; P52294; IMA1_HUMAN; M.
DR   CleanEx; HS_KPNA1; -; -.
//
ID   IPI00301082.1         IPI;      PRT;   309 AA.
AC   IPI00301082;
DT   06-JUN-2003 (IPI Human rel. 2.20, Created)
//

つまり、データベース エントリは、IPI コードを含む行で始まり、二重スラッシュで終わります。特定の IPI コードに関連付けられた情報を取得したいと考えています。IPIIPI00303292.1コードから次の//.

正規表現の Rubular テストは/(IPI00303292\.1).*\/\//m、表示されたテキスト全体 (つまり 2 つのエントリ) を取得し、最後のものを認識し//、2 つの間の 2 番目をスキップします。

更新: こんにちは、あなたの貴重な提案に基づいて、私の目的に使用できるプログラムを取得することに近づいていると思います。コードは次のとおりです。

matches = []
no_matches = []

ipi = File.open('mini_alphaIPI.txt').collect do | var | # read the file containing IPI search codes
    var = var.chomp 

db = File.open('mini_human.dat') # read the file containing IPI data

db.readlines.map(&:chomp).slice_before(%r(\A//)).each do |db_record|
  db_record.shift
  next if db_record.empty?

matches.push(db_record) if db_record.first.include?(var)

if db_record.first.include?(var)  then
    matches.push(db_record)
    else
    no_matches.push(var)
end
end
end

File.open('out_raw.txt', "wb") do |file|
     matches.each do |z|
      file.puts z
  end
end

ここで解決すべき最後の問題は、適切に選択されたポジティブ ヒットの出力ファイルに 2 つのコピーが含まれていることです。そんなミスはやめられません。助けてください 。

4

3 に答える 3

1

slice_beforeRubyには、この種の問題に適したツールが装備されています。

require 'pp'

DATA.readlines.slice_before(%r(\A//)).each do |db_record|
  pp db_record
end

__END__
//
ID   IPI00303292.1         IPI;      PRT;   538 AA.
AC   IPI00303292;
DR   Superfamily; SSF48371; ARM; 1.
DR   UniProt/Swiss-Prot; P52294; IMA1_HUMAN; M.
DR   CleanEx; HS_KPNA1; -; -.
//
ID   IPI00301082.1         IPI;      PRT;   309 AA.
AC   IPI00301082;
DT   06-JUN-2003 (IPI Human rel. 2.20, Created)
//

コード出力の実行:

["// \ n"、
 "ID IPI00303292.1 IPI; PRT; 538AA。\n"、
 "AC IPI00303292; \ n"、
 "DRスーパーファミリー;SSF48371;ARM; 1. \ n"、
 "DR UniProt / Swiss-Prot; P52294; IMA1_HUMAN; M. \ n"、
 "DRCleanEx;HS_KPNA1;-;-。\n"]
["// \ n"、
 "ID IPI00301082.1 IPI; PRT; 309AA。\n"、
 "AC IPI00301082; \ n"、
 "DT 06-JUN-2003(IPI Human rel。2.20、作成済み)\ n"]
["// \ n"]

配列をスキャンし、パターンに一致する行(この場合は%r(\A//)、英語では「2つのスラッシュで始まる行」)の出現時に配列を分割します。結果として得られる配列の配列は、で区切られたレコードの各グループになります//

行の末尾に新しい行があることに注意してください。これは、次を使用して修正できます。

DATA.readlines.map(&:chomp).slice_before(%r(\A//)).each do |db_record|

最初のサブ配列//エントリをスキップする場合は、次を使用します。

pp db_record[1..-1]

また:

db_record.shift
pp db_record

クリーンアップ後、コードは次のようになります。

require 'pp'

DATA.readlines.map(&:chomp).slice_before(%r(\A//)).each do |db_record|
    db_record.shift
    pp db_record
end

そしてそれを実行すると次のようになります:

["ID IPI00303292.1 IPI; PRT; 538 AA。"、
 "AC IPI00303292;"、
 "DRスーパーファミリー;SSF48371;ARM; 1."、
 "DR UniProt / Swiss-Prot; P52294; IMA1_HUMAN; M。"、
 "DRCleanEx;HS_KPNA1;-;-。"]
["ID IPI00301082.1 IPI; PRT; 309 AA。"、
 "AC IPI00301082;"、
 "DT 06-JUN-2003(IPI Human rel。2.20、作成済み)"]
[]

2つの調整で完了です。

DATA.readlines.map(&:chomp).slice_before(%r(\A//)).each do |db_record|
  db_record.shift
  next if db_record.empty?

  pp db_record if db_record.first['IPI00303292.1']

end

どの出力:

["ID IPI00303292.1 IPI; PRT; 538 AA。"、
 "AC IPI00303292;"、
 "DRスーパーファミリー;SSF48371;ARM; 1."、
 "DR UniProt / Swiss-Prot; P52294; IMA1_HUMAN; M。"、
 "DRCleanEx;HS_KPNA1;-;-。"]
于 2013-01-25T16:28:46.763 に答える
1

これは、貪欲な量指定子を使用することによって引き起こされる典型的な問題*です。*?代わりに貪欲でない量指定子を使用してください。

于 2013-01-25T16:01:29.417 に答える
0
  • リスト項目

.この場合、正規表現のアプローチは非常に難しく、問題はマッチングにも依存していると思います/

この正規表現でほぼ達成しました:

%r{
  //\n                  # Match '//' and new line
  (?<item>              # Capture the item...
    [\n\w\s.,;\-\(\)]+  # And here comes the !"#%&@ł
  )                     # You need this to match a single appearance of '/' 
}x                      # e.g., not '//', and partial regex negation is a bit tricky... 

split('//')ただし、そこからプロセスを使用して続行する方がはるかに簡単です。

DATA.split('//').each do |item|
  item.each_line do |line|
    # etc
  end
end

ハウディ: これは動作しますhttp://rubular.com/r/kH12xUyxR9

%r{
  (//)?\n
  (?<item>.+?)
  \n//
}xm

しかし、これは単なる好奇心のためです。真剣に、ただ使用してsplit('//')ください。

于 2013-01-25T18:39:16.380 に答える