1

我需要开发一种方法,从字符串中提取数据库中记录的含义。以下是 a 字符串的示例:

MyString = "Purse $75,000. (up To $14,250 Nysbfoa) For Maidens, Fillies And Mares Three Years Old And Upward. Three Year Olds, 118 Lbs.; Older, 123 Lbs. One And One Eighth Miles. (Inner turf)"    

给定字符串,我需要以可以创建race_record的方式处理它:

race_record[:purse] = 75000 
race_record[:race_type] = "Maidens"
race_record[:sex] = "Fillies And Mares"
race_record[:age] = "Three Year Old And Upward"
race_record[:distance] = "One And One Eighth Miles"
race_record[:surface] = "inner turf"

我打算使用 ruby​​ 和一系列正则表达式来提取数据。例如:

race_record[:purse] = Mystring.scan(/(?<=\Purse\s[$])(.*?)(?=\.)/)
race_record[:race_type] = Mystring.sub(....)
etc.

我的问题不是正确的正则表达式是什么。鉴于目标,我提出的方法是正确的方法,还是有更好的方法,甚至是可以完成繁重工作的宝石?

4

2 回答 2

1

You could use one regex to extract all the relevant parts into capturing groups at once;

regexp = 
    /Purse\s\$          # Leading text
    ([\d,]+)            # Group 1
    .*?For\s            # Intervening text
    (\w+)               # Group 2
    ,\s                 # Intervening text
    (\w+\sAnd\s\w+)     # Group 3, etc. etc.
    \s
    ([^.]*)
    \.[^;]*;[^.]*\.\s
    ([^.]*)
    \.\s\(
    ([^()]*)
    \)/x

Then you can do

irb(main):025:0> match = regexp.match(mystring)
=> #<MatchData "Purse $75,000. (up To $14,250 Nysbfoa) For Maidens, Fillies And    Mares Three Years Old And Upward. Three Year Olds, 118 Lbs.; Older, 123 Lbs. One And One Eighth Miles. (Inner turf)" 
   1:"75,000" 2:"Maidens" 3:"Fillies And Mares" 4:"Three Years Old And Upward" 
   5:"One And One Eighth Miles" 6:"Inner turf">
irb(main):026:0> match[1]
=> "75,000"
irb(main):027:0> match[2]
=> "Maidens"
...etc.
于 2012-09-30T15:43:29.547 回答
1

如果您的输入是相当结构化的,即它具有特定且已知的语法,您可以构建一个“解析器”来解析语法。

在过去,我们会使用 yacc 和 lex 这两个旧的 unix 工具来构建编译器。Yacc 和 Lex 有 Ruby 实现。虽然最初的意图是输出较低级别的代码(例如构建真正编译器时的机器汇编代码),但当您的解析器识别出特定的语法结构时,没有什么可以阻止您调用任何 ruby​​ 代码。

注意:即使有一个 Yacc/lex Ruby gem,我不会说它会“做重活”,学习 yacc 和 lex 的学习曲线很小。从长远来看,使用 yacc/lex 之类的东西会让你的生活更轻松,特别是如果你有一个很大的语法并且必须不断调整它。

于 2012-09-30T15:50:36.963 回答