Parsing 如何创建配方/成分分析器
给出一行,例如 一磅牛肉 我想提取成分。最初我只对成分名称感兴趣 我看了Ruby著名的时间分析器,喜欢它使用正则表达式Parsing 如何创建配方/成分分析器,parsing,Parsing,给出一行,例如 一磅牛肉 我想提取成分。最初我只对成分名称感兴趣 我看了Ruby著名的时间分析器,喜欢它使用正则表达式 def self.scan_for_month_names(token) scanner = {/^jan\.?(uary)?$/ => :january, /^feb\.?(ruary)?$/ => :february, /^mar\.?(ch)?$/ => :march, /^apr\.?
def self.scan_for_month_names(token)
scanner = {/^jan\.?(uary)?$/ => :january,
/^feb\.?(ruary)?$/ => :february,
/^mar\.?(ch)?$/ => :march,
/^apr\.?(il)?$/ => :april,
/^may$/ => :may,
/^jun\.?e?$/ => :june,
/^jul\.?y?$/ => :july,
/^aug\.?(ust)?$/ => :august,
/^sep\.?(tember)?$/ => :september,
/^oct\.?(ober)?$/ => :october,
/^nov\.?(ember)?$/ => :november,
/^dec\.?(ember)?$/ => :december}
scanner.keys.each do |scanner_item|
return Chronic::RepeaterMonthName.new(scanner[scanner_item]) if scanner_item =~ token.word
end
return nil
结束
然而在我的例子中,我可能需要为每种成分创建300多个正则表达式
我还必须考虑一些同义词,如香菜叶
我以前从未做过语法分析,但是在这里使用正则表达式仍然是最好的方法吗。我想不出任何其他合理的替代方案。我想我应该从对每行运行一系列正则表达式检查开始,并在运行时调整解析的文本。例如(伪代码): 首先,检查指令:
/^(add|fold in|stir in|etc...)/
如果找到指令,请将其从行中删除,设置标志,然后继续:
instruction = $1
this_line = this_line.substring(instruction.length())
如果找到指令,检查是否有后续指令(如“和封面”或“和搁置”)
如果找到,将其剥离并插入配方的下一行之前
instruction = instruction.substring(0, instuction.length - $1.length - $2.length)
splice $2 into the array of lines immediately following this one
下一步,也许你要检查一个介词:
/((?in)to\s(.+)/
如果发现,您可以使用它来检查设备名称、碗、量杯等。
即使不使用它,也可以从正在解析的字符串中删除它,以改进匹配
最后,真正的工作是用剩下的文本完成的:
Check against /^(\d+\s+(?a\s)?\w+)\s*(?of\s*)?(.+)$/
这将为您提供包含计量单位的$1
,以及包含成分的$2
泡沫。冲洗重复
在那之后,用你的应用程序对这些信息施展魔法。我想我应该先对每一行运行一系列正则表达式检查,然后在运行过程中调整解析的文本。例如(伪代码): 首先,检查指令:
/^(add|fold in|stir in|etc...)/
如果找到指令,请将其从行中删除,设置标志,然后继续:
instruction = $1
this_line = this_line.substring(instruction.length())
如果找到指令,检查是否有后续指令(如“和封面”或“和搁置”)
如果找到,将其剥离并插入配方的下一行之前
instruction = instruction.substring(0, instuction.length - $1.length - $2.length)
splice $2 into the array of lines immediately following this one
下一步,也许你要检查一个介词:
/((?in)to\s(.+)/
如果发现,您可以使用它来检查设备名称、碗、量杯等。
即使不使用它,也可以从正在解析的字符串中删除它,以改进匹配
最后,真正的工作是用剩下的文本完成的:
Check against /^(\d+\s+(?a\s)?\w+)\s*(?of\s*)?(.+)$/
这将为您提供包含计量单位的$1
,以及包含成分的$2
泡沫。冲洗重复
在那之后,用这些信息做你的应用程序能做的任何事情。首先,我假设成分并不总是以
成分的数量单位的形式出现-否则,这将是一项非常简单的任务(只需在的之后复制子字符串即可)
这是一个困难的问题——解决办法不会很简单
我认为在这里使用正则表达式可能不是最好的方法:
- 正如你所提到的,你必须为每种语言写很多表达
配料
- 你可能的配料清单总是有限的
根据regex列表,如果没有
编辑更多
- 分析某些成分将非常困难(
奶酪,1磅(帕尔马干酪)
)
我认为这就是方法。你有非结构化的输入,但是在一个非常有限的环境中
也许与直觉相反,我认为找到成分的最好方法可能是不要去寻找它——而是去寻找其他的东西
- 数字(数量)
- 单位(磅、茶匙等)
- 配料
而且检测数字和单位非常容易,首先识别这些数字和单位,然后提取成分应该很简单
如果您使用词性标记,很容易识别相关单词:
[('1','LS'),('pound','NN'),('of','IN'),('Beef','NNP')]
从这里开始,您可能需要使用a。为此,您需要在大量的行(例如,数百行)上手动标记成分。可能需要使用一些好的功能:
- 单词在行中的位置
- 存在于预先计算的成分字典中(可能使用某些部分字符串匹配度量,如
- 词性标记器的输出
- 单词前后(如果单词前有“of”,很可能是成分
我相信你在写了几行之后,一定能找到无数其他人
最后,我认为有些行很难处理。1磅帕尔马干酪,1磅埃门塔尔干酪
:你必须推断第二种配料也是奶酪
至于软件,如果你能选择要使用的语言,python就有其神奇之处。我不能保证其他语言的工具包,但也许其他人会。首先,我假设成分并不总是以成分的数量单位的形式出现,否则,这将是一项非常琐碎的任务(只需在
这是一个困难的问题——解决办法不会很简单
我认为在这里使用正则表达式可能不是最好的方法:
- 正如你所提到的,你必须为每种语言写很多表达
配料
- 你可能的配料清单总是有限的
根据regex列表,如果没有
编辑更多
- 分析某些成分将非常困难(
奶酪,1磅(帕尔马干酪)
)
我认为这就是方法。你有非结构化的输入,但是在一个非常有限的环境中
也许与直觉相反,我认为找到配料的最好方法可能是不去寻找它——寻找所有的东西