在按行读取文件时保存一个延伸到多行的值

时间:2016-04-25 13:16:37

标签: python python-2.7

我正在编写一个小的python脚本,它从dir中的几个.c文件中读取参数及其值。参数通常采用以下格式:

uint8 param1 = 1;
sint8 param2 = 2;

但是,有时它们看起来像这样:

param3 = {
1, 2, 3,
4, 5, 6
};

甚至:

param4 = {
1, 2, 3,
{
4, 5, 6
},
};

正如您怀疑在涉及param3 and param4的情况下,该行将为param3 = {并且param4相同,因此不包含任何实际值。我想我会在通过搜索" {"来调用价值获取方法之前解决它。在一行中,如果找到了,那么通过找到&#34 ;;"的下一次迭代,找到它以某种方式结束。在包含" {"并且应该删除任何换行符,制表符和空格。 这是我希望方法在正确运行时显示的输出。

param3 = {1,2,3,4,5,6};
param4 = {1,2,3,{4,5,6},};

这是我正在使用的布局,formatFile(line)是我需要帮助的方法。

for root, dirs, files in os.walk(PATH_DST_SOURCE):
    for file in files:
        if file.endswith('.c'):
            with open(os.path.join(root, file), 'r') as this:
                for line in this:
                    formatFile(line)

不幸的是,我不知道如何做到这一点,并希望得到一些帮助,甚至可以在正确的方向上轻推。当然,如果有更好的方法来解决我的问题,那么也欢迎这些!

4 个答案:

答案 0 :(得分:3)

你可以尝试一种简单的方法(诚然不是逐行阅读):

with open(os.path.join(root, file), 'r') as this:
    content = this.read().replace('\n', '')  # whole file in one line
    content = content.replace(';', ';\n')    # add linebreak after each ';'
    lines = content.split('\n')  # now each line contains one parameter assignment

答案 1 :(得分:1)

提出一个完全不同的解决方案......只需稍加考虑一下......

将C文件解析为字符串通常是一项非常繁琐的工作,非常容易出错。您可以尝试使用一些正则表达式,但通常您会发现自己说:

  • 哦......我从没想过他们可以在那里放一个空间......
  • 如果他们在这里发表评论怎么办......
  • 如果有人添加无用的括号怎么办...

如果你想构建一些健壮的东西,不要自己解析代码......尝试找到适合你的东西。 我会尝试做的例如是你的C文件的Swig接口,然后直接访问变量。

一般文档:http://www.swig.org/Doc1.3/Python.html

访问全球变量:http://www.swig.org/Doc1.3/Python.html#Python_nn16

如果您可以使用此解决方案,您唯一需要做的就是编写几行小接口文件,将其作为Swig软件的输入,这将为您生成一个包装C文件的python模块。

修改

这就是你在案件中可以做的事情:

1.安装Swig 2.创建一个文件myInterface.i,如下所示:

/* File: myInterface.i */

%include "stdint.i"
%{
#include "file.h"
%}
extern uint8 param1;
extern uint8 param2;
  1. 运行命令swig -python myInterface.i这将为您生成头文件的python包装器。

  2. 在Python脚本中导入此文件,并直接从头文件中访问变量。

  3. 我不记得该怎么做数组,但他们肯定也可以访问!

答案 2 :(得分:1)

您可以这样尝试:拥有一个语句列表和一个包含当前语句的字符串;添加到当前语句,直到它以;结尾,然后将其添加到语句列表中。

with open("file.c") as f:
    statements = []
    cur = ""
    for line in f:
        cur += line.strip()
        if cur.endswith(";"):
            statements.append(cur)
            cur = ""

当然,这假设每个语句结尾;实际上都在行的末尾,而不是,例如然后是行注释,或(部分)另一个语句。如果你还想解决这些问题,事情变得更加复杂(在行或块注释中或类似字符串中的类似语句的代码),你应该寻找一些现有的解析器库。

答案 3 :(得分:0)

使用正则表达式:

import re
pattern = r'((?P<type>\w+)\s+)?(?P<name>\w+)\s*=\s*(?P<value>.+?);'

with open("example.c") as cfile:
    assignments = []
    for m in re.finditer(pattern, cfile, re.DOTALL):
        dic = m.groupdict()
        dic["value"] = dic["value"].replace("\n", " ")
        assignments.append(dic)

    print assignments

从此代码中,您将获得一个字典列表,其中包含键"type"(已分配变量的数据类型),"name"(已分配变量名称)和"value"(无论是否已分配)。每个字典代表一个任务。

输出为此(为清晰起见,手动添加换行符):

[{'type': 'uint8', 'name': 'param1', 'value': '1'}, 
 {'type': 'sint8', 'name': 'param2', 'value': '2'}, 
 {'type': None, 'name': 'param3', 'value': '{ 1, 2, 3, 4, 5, 6 }'}, 
 {'type': None, 'name': 'param4', 'value': '{ 1, 2, 3, { 4, 5, 6 }, }'}]

...对于此输入文件:

uint8 param1 = 1;
sint8 param2 = 2;

param3 = {
1, 2, 3,
4, 5, 6
};

param4 = {
1, 2, 3,
{
4, 5, 6
},
};