2014-02-19 39 views
0

我不是很擅長解析文件,但有一些我想完成的事情。以下是包含一些require語句的.lua腳本的片段。我想用Python來解析這個.lua文件,並將'require'語句拉出來。如何用Python解析.lua文件並提取require語句?

例如,這裏有需要的語句:

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

從上面的例子中我會再像從所需文件分割的目錄。在示例'require'common.acme_1''中,該目錄將是常見的,並且所需的文件將是acme_1。然後,我會將.lua擴展添加到acme_1。我需要這些信息,以便我可以驗證文件系統中是否存在文件(我知道該怎麼做),然後對luac(編譯器)進行驗證,以確保它是一個有效的lua文件(我也知道該怎麼做)。

我只需要幫助,使用Python拉出這些require語句,並從文件名中分割出目錄名。

+4

爲什麼不讓如果文件不存在'require'失敗?請記住,'require'會在各種來源中搜索匹配的模塊,其中可能包含一系列文件系統位置。模塊'acme_3'也可能來自名爲'acme_3/init.lua'的文件和標準設置。而且這忽略了編譯到可執行文件或動態加載的具有相似規則的編譯模塊的模塊問題。或者,通過'package.loaders'提供的模塊系統的可擴展性。簡而言之,重複「require」的行爲並不是微不足道的。 – RBerteig

回答

1

這裏亞去!

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 
+0

工作得很好。謝謝。 – user2643864

0

這是直截了當

一個襯墊是偉大的,但他們耗費太多精力提前瞭解,這是不是在我看來

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) 
+0

嗯雖然我想要的路徑和文件並排 – deinonychusaur

0

這裏使用正則表達式的工作是一個瘋狂的單內膽,不知道這是否是你想要的到底是什麼,最肯定不是最優化的一個...

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']] 
0
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'。 print語句顯示結果。

+0

請通過添加一些解釋來闡述答案。 –

2

您可以使用內建的字符串方法來做到這一點,但由於解析有點複雜(路徑可能是多個部分),最簡單的解決方案可能是使用正則表達式。如果您使用的正則表達式,就可以做的解析和分割用組:(。包括結尾)

import re 


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


finds = re.findall(r'require\s+"(([^."]+\.)*)?([^."]+)"', 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'}] 
+0

比我的解決方案好得多,更多的工作在重新部分。 – deinonychusaur

+0

真棒,也許替換「。」在路徑中用「/」 –

0

你可以使用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'^require\s+(\'|")([^\'"]+)(\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'^require\s+(\'|")([^\'"]+)(\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 
+0

爲什麼downvote? – dawg

+0

工作得很好。謝謝。 – user2643864