我需要开发一种方法,从字符串中提取数据库中记录的含义。以下是字符串的示例:
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.
我的问题不在于正确的正则表达式是什么。鉴于目标,我提出的方法是正确的方法,还是有更好的方法,甚至是可以做繁重的宝石?
答案 0 :(得分:1)
您可以使用一个正则表达式将所有相关部分一次性提取到捕获组中;
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
然后你可以做
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.
答案 1 :(得分:1)
如果您的输入结构合理,即它具有特定且已知的语法,您可以构建一个“解析器”来解析语法。
在过去,我们使用yacc和lex这两个用于构建编译器的旧unix工具。 Yacc和Lex有Ruby实现。虽然最初的意图是输出较低级别的代码(例如构建真实编译器时的机器汇编代码),但是当解析器识别出特定的语法结构时,没有什么可以阻止您调用任何ruby代码。
注意:即使有一个Yacc / lex Ruby宝石出现在那里,我也不会说它会“做重的提升”,学习yacc和lex的学习曲线很小。使用像yacc / lex这样的东西会让你的生活变得更轻松,特别是如果你有很大的语法并且必须不断调整它。