我正在尝试解析伪英语脚本,并希望将其转换为另一种机器可读语言。 但是该脚本过去是许多人编写的,每个人都有自己的写作风格。
一些例子是:
问题在于它并不总是合乎逻辑且不一致
我看过正则表达式,并匹配了某些单词。可以,但是当我需要知道下一个单词时(例如,在“ Word 24”中,我将匹配“ Word”,然后尝试确定下一个标记是否为数字)。对于“单词”,我需要查找要设置的单词及其值。
在示例1中,它应产生Set word 45 to hex 331
和Set word 46 to hex 331
或者Set word 45 to hex 331 and word 46 to hex 331
我尝试在re上使用findall方法-这样只会给我匹配的单词,然后我不得不尝试手动找出下一个单词(即值)
或者,我可以使用空格分割字符串并手动处理每个单词,然后能够执行类似的操作
假设列表为
['On', 'device1:', 'set', 'Word', '1', '', 'to', '88', 'and', 'word', '2', 'to', '2151']
for i in range (0,sp.__len__()):
rew = re.search("[Ww]ord", sp[i])
if rew:
print ("Found word, next val is ", sp[i+1])
有没有更好的方法来做我想做的事?我稍微看了一下分词,但是不确定该语言是否一开始就没有结构。
答案 0 :(得分:1)
我建议您开发一个程序,逐步探索人们用来编写脚本的语法。
例如,示例中的每条指令似乎都分为设备部分和设置部分。因此,您可以尝试将每行与正则表达式^(.+) set (.+)
相匹配。如果发现与该模式不匹配的行,请打印出来。检查输出,找到与其中一些匹配的常规模式,向程序中添加相应的正则表达式(或修改现有的正则表达式),然后重复。继续操作,直到您(以非常一般的方式)识别出输入中的每一行为止。
(由于大写字母似乎不一致,因此您可以进行不区分大小写的匹配,也可以在开始处理之前将每行转换为小写字母。更普遍的是,您可能会发现其他“规范化”可以简化后续处理。例如,如果人们对于空格不一致,可以将每次运行的空白字符都转换为一个空格。)
(如果您的输入存在印刷错误,例如有人为“ set”写了“ ste”,那么您可以更改正则表达式以允许该(... (set|ste) ...
),或转到(的副本)输入文件,然后修正拼写错误。)
然后返回与^(.+) set (.+)
匹配的行,仅打印出每组的第一组,并对那些子字符串重复上述过程。
然后在每个“设置”指令中为第二组重复该过程。依此类推,递归地进行。
最终,您的程序实际上将是脚本语言的解析器。此时,您可以开始添加代码,以将每个可识别的构造转换为输出语言。
根据您使用Python的经验,您可以找到使代码简洁的方法。
答案 1 :(得分:0)
根据这些字符串的实际需求,您可以使用解析器,例如parsimonious
:
from parsimonious.nodes import NodeVisitor
from parsimonious.grammar import Grammar
grammar = Grammar(
r"""
command = set operand to? number (operator number)* middle? to? numsys? number
operand = (~r"words?" / "speed") ws
middle = (~r"[Ww]ords" / "bits")+ ws number
to = ws "to" ws
number = ws ~r"[-\d.]+" "kts"? ws
numsys = ws ("oct" / "hex") ws
operator = ws "and" ws
set = ~"[Ss]et" ws
ws = ~r"\s*"
"""
)
class HorribleStuff(NodeVisitor):
def __init__(self):
self.cmds = []
def generic_visit(self, node, visited_children):
pass
def visit_operand(self, node, visited_children):
self.cmds.append(('operand', node.text))
def visit_number(self, node, visited_children):
self.cmds.append(('number', node.text))
examples = ['Set word 45 and 46 to hex 331',
'set words 45 and 46 bits 3..7 to 280',
'set word 45 to oct 332',
'set speed to 60kts Words 3-4 to hex 34']
for example in examples:
tree = grammar.parse(example)
hs = HorribleStuff()
hs.visit(tree)
print(hs.cmds)
这会产生
[('operand', 'word '), ('number', '45 '), ('number', '46 '), ('number', '331')]
[('operand', 'words '), ('number', '45 '), ('number', '46 '), ('number', '3..7 '), ('number', '280')]
[('operand', 'word '), ('number', '45 '), ('number', '332')]
[('operand', 'speed '), ('number', '60kts '), ('number', '3-4 '), ('number', '34')]