如何使用 Python 解析 .lua 文件并提取 require 语句



我不太擅长解析文件,但有一些我想完成的事情。 下面是具有一些 require 语句的 .lua 脚本片段。 我想使用 Python 解析这个.lua文件并提取"require"语句。

例如,下面是 require 语句:

require "common.acme_1"
require "common.acme_2"
require "acme_3"
require "common.core.acme_4"

上面的示例中,我想从所需的文件中拆分目录。 在示例中"需要"common.acme_1",目录将是通用的,所需的文件将是acme_1。 然后,我将.lua扩展添加到acme_1。 我需要这些信息,以便我可以验证文件是否存在于文件系统上(我知道该怎么做),然后针对luac(编译器)以确保它是一个有效的lua文件(我也知道如何做)。

我只需要帮助使用 Python 将这些 require 语句拉出并将目录名称与文件名分开。

您可以使用内置字符串方法执行此操作,但由于解析有点复杂(路径可以是多部分),最简单的解决方案可能是使用正则表达式。 如果您使用的是正则表达式,则可以使用组进行解析和拆分:

import re

data = 
'''
require "common.acme_1"
require "common.acme_2"
require "acme_3"
require "common.core.acme_4"
'''

finds = re.findall(r'requires+"(([^."]+.)*)?([^."]+)"', data, re.MULTILINE)
print [dict(path=x[0].rstrip('.'),file=x[2]) for x in finds]
第一组是路径(

包括尾随的.),第二组是匹配重复路径部分所需的内部组(丢弃),第三组是文件名。 如果没有路径,你会得到path=''.

输出:

[{'path': 'common', 'file': 'acme_1'}, {'path': 'common', 'file': 'acme_2'}, {'path': '', 'file': 'acme_3'}, {'path': 'common.core', 'file': 'acme_4'}]

来吧!

import sys
import os.path
if len(sys.argv) != 2:
    print "Usage:", sys.argv[0], "<inputfile.lua>"
    exit()
f = open(sys.argv[1], "r")
lines = f.readlines()
f.close()
for line in lines:
    if line.startswith("require "):
        path = line.replace('require "', '').replace('"', '').replace("n", '').replace(".", "/") + ".lua"
        fName = os.path.basename(path)
        path = path.replace(fName, "")
        print "File: " + fName
        print "Directory: " + path
        #do what you want to each file & path here

这是一个疯狂的单行,不确定这是否正是你想要的,而且肯定不是最理想的......

In [270]: import re
In [271]: [[s[::-1] for s in rec[::-1].split(".", 1)][::-1] for rec in re.findall(r"require "([^"]*)", text)]
Out[271]: 
[['common', 'acme_1'],
 ['common', 'acme_2'],
 ['acme_3'],
 ['common.core', 'acme_4']]

这是直截了当的

一个衬里很棒,但它们需要花费太多精力才能尽早理解,在我看来这不是使用正则表达式的工作

mylines = [line.split('require')[-1] for line in open(mylua.lua).readlines() if line.startswith('require')]
paths = []
for line in mylines:
    if 'common.' in line:
        paths.append('common, line.split('common.')[-1]
    else:
        paths.append('',line)

你可以使用 finditer:

lua='''
require "common.acme_1"
require "common.acme_2"
require "acme_3"
require 'common.core.acme_4'
'''
import re
print [m.group(2) for m in re.finditer(r'^requires+('|")([^'"]+)(1)', lua, re.S | re.M)]
# ['common.acme_1', 'common.acme_2', 'acme_3', 'common.core.acme_4']

然后只需在"."上拆分即可拆分为路径:

for e in [m.group(2) for m in re.finditer(r'^requires+('|")([^'"]+)(1)', lua, re.S | re.M)]:
    parts=e.split('.')
    if parts[:-1]:
        print '/'.join(parts[:-1]), parts[-1]
    else:
        print parts[0]  

指纹:

common acme_1
common acme_2
acme_3
common/core acme_4
file = '/path/to/test.lua'

def parse():
    with open(file, 'r') as f:
        requires = [line.split()[1].strip('"') for line in f.readlines() if line.startswith('require ')]
    for r in requires:
        filename = r.replace('.', '/') + '.lua'
        print(filename)

with 语句将打开有问题的文件。 下一行创建以"require"开头的所有行的列表并拆分它们,忽略"require"并仅抓取最后一部分并去除双引号。 然后浏览列表并用斜杠替换点并附加".lua"。 打印语句显示结果。

最新更新