0

我需要帮助 Ruby 中的正则表达式失败,我不知道为什么。我正在使用 Ruby 从大型生物数据库中获取部分文本,该数据库具有以下结构(为简单起见,我将仅显示两项):

//
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 代码相关的信息。假设我只想获取IPI00303292.1从 IPI 代码到以下内容的文本行//

正则表达式的 Rubular 测试/(IPI00303292\.1).*\/\//m抓取整个显示的文本(即两个条目),识别最后一个//,同时跳过两者之间的第二个。

更新: 嗨,根据您的宝贵建议,我想我已经接近为我的目的获得可用的程序了。代码是:

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

现在要解决的最后一个问题是,我在正确选择的正面命中的输出文件中获得了两个副本。我无法摆脱这样的错误。请帮忙 。

4

3 回答 3

1

Ruby 配备了slice_before一个很好的工具来解决这类问题:

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;538 AA。\n",
 "AC IPI00303292;\n",
 "DR 超家族;SSF48371;ARM;1.\n",
 "DR UniProt/Swiss-Prot;P52294;IMA1_HUMAN;M.\n",
 "DR CleanEx;HS_KPNA1;-;-。\n"]
["//\n",
 "ID IPI00301082.1 IPI;PRT;309 AA。\n",
 "AC IPI00301082;\n",
 "DT 06-JUN-2003 (IPI Human rel. 2.20, Created)\n"]
["//\n"]

它扫描一个数组,在出现与模式匹配的行时将其中断,在这种情况下,模式是%r(\A//),或者在英语中,“以两个正斜杠开头的行”。生成的数组数组将是由 分隔的每组记录//

请注意,这些行有尾随的换行符。可以使用以下方法修复:

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.",
 “DR CleanEx;HS_KPNA1;-;-。”]
["ID IPI00301082.1 IPI;PRT;309 AA。",
 "AC IPI00301082;",
 “DT 06-JUN-2003(IPI Human rel. 2.20,已创建)”]
[]

两次调整,你就完成了:

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.",
 “DR CleanEx;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 回答