我有这个字符串:
%{Children^10 Health "sanitation management"^5}
我想将其转换为将其标记为哈希数组:
[{:keywords=>"children", :boost=>10}, {:keywords=>"health", :boost=>nil}, {:keywords=>"sanitation management", :boost=>5}]
我知道 StringScanner 和 Syntax gem但我找不到足够的代码示例。
有什么建议吗?
最佳答案
对于真正的语言,词法分析器是必经之路 - like Guss said .但是如果完整的语言只是和你的例子一样复杂,你可以使用这个快速 hack:
irb> text = %{Children^10 Health "sanitation management"^5}
irb> text.scan(/(?:(\w+)|"((?:\\.|[^\\"])*)")(?:\^(\d+))?/).map do |word,phrase,boost|
{ :keywords => (word || phrase).downcase, :boost => (boost.nil? ? nil : boost.to_i) }
end
#=> [{:boost=>10, :keywords=>"children"}, {:boost=>nil, :keywords=>"health"}, {:boost=>5, :keywords=>"sanitation management"}]
如果您正在尝试解析常规语言,那么此方法就足够了 - 尽管使语言变得非常规并不需要更多的复杂性。
正则表达式的快速分解:
\w+
匹配任何单词关键词(?:\\.|[^\\"]])*
使用非捕获括号 ((?:...)
) 来匹配转义双引号字符串的内容 - 转义符号(\n
、\"
、\\
等)或任何单个字符那不是转义符号或结束引号。"((?:\\.|[^\\"]])*)"
仅捕获引用关键字短语的内容。(?:(\w+)|"((?:\\.|[^\\"])*)")
匹配任何关键字 - 单个术语或短语,捕获单个术语放入$1
并将短语内容放入$2
\d+
匹配一个数字。\^(\d+)
捕获插入符号 (^
) 后的数字。由于这是第三组捕获括号,它将被捕获到$3
。(?:\^(\d+))?
捕获插入符号后的数字(如果有),否则匹配空字符串。
String#scan(regex)
尽可能多次将正则表达式与字符串匹配,输出“匹配”数组。如果正则表达式包含捕获括号,则“匹配项”是捕获的项目数组 - 因此 $1
变为 match[0]
,$2
变为 match[1]
等。任何未与部分字符串匹配的捕获括号都映射到结果“匹配”中的 nil
条目。
#map
然后获取这些匹配项,使用一些 block 魔术将每个捕获的术语分解为不同的变量(我们可以做 do |match| ; word,phrase,boost = * match
),然后创建你想要的散列。 word
或 phrase
中的一个将是 nil
,因为两者都无法与输入匹配,所以 (word || phrase)
将返回非nil
的,而#downcase
会将其转换为全部小写。 boost.to_i
将字符串转换为整数,而 (boost.nil? ? nil : boost.to_i)
将确保 nil
提升保持不变无
。
关于ruby - 我如何在 Ruby 中标记这个字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/713559/