Pyparsing:如何解析数据并编辑.txt文件中的特定值?

6 投票
4 回答
2359 浏览
提问于 2025-04-16 08:48

我的数据存放在一个.txt文件里(不,我不能换成其他格式),内容大概是这样的:

varaiablename = value
something = thisvalue
youget = the_idea

这是我目前的代码(参考了Pyparsing的例子):

from pyparsing import Word, alphas, alphanums, Literal, restOfLine, OneOrMore, \
empty, Suppress, replaceWith

input = open("text.txt", "r")
src = input.read()

# simple grammar to match #define's
ident = Word(alphas + alphanums + "_")
macroDef = ident.setResultsName("name") + "= " + ident.setResultsName("value") + Literal("#") + restOfLine.setResultsName("desc")
for t,s,e in macroDef.scanString(src):
print t.name,"=", t.value

那么我该怎么告诉我的脚本去修改某个特定变量的值呢?
举个例子:
我想把varaiablename的值从value改成new_value。
所以其实就是变量 = (我们想要编辑的数据)。

我可能需要说明一下,我并不想直接打开文件去把值从value改成new_value,而是想解析数据,找到这个变量,然后给它一个新值。

4 个回答

1

其实,你应该看看配置解析模块。这个模块正好可以解析你写的那种语法(你只需要在开头加上[section])。

如果你还是想用自己的方法,可以创建一个字典:

dictt = {}
for t,s,e in macroDef.scanString(src):
   dictt[t.name]= t.value
dictt[variable]=new_value
6

虽然你已经选择了其他答案,但让我来回答你最初的问题,也就是如何使用pyparsing来实现这个功能。

如果你想在一段文本中进行选择性的修改,那么使用transformString会比scanString更合适(虽然scanString或searchString也可以用来验证你的语法表达式,看看是否有匹配的文本)。transformString会在扫描文本寻找匹配项时,对你的输入字符串进行标记抑制或解析动作的修改。

# alphas + alphanums is unnecessary, since alphanums includes all alphas
ident = Word(alphanums + "_")
# I find this shorthand form of setResultsName is a little more readable
macroDef = ident("name") + "=" + ident("value")

# define values to be updated, and their new values
valuesToUpdate = {
    "variablename" : "new_value"
    }

# define a parse action to apply value updates, and attach to macroDef
def updateSelectedDefinitions(tokens):
    if tokens.name in valuesToUpdate:
        newval = valuesToUpdate[tokens.name]
        return "%s = %s" % (tokens.name, newval)
    else:
        raise ParseException("no update defined for this definition")
macroDef.setParseAction(updateSelectedDefinitions)

# now let transformString do all the work!
print macroDef.transformString(src)

结果是:

variablename = new_value
something = thisvalue
youget = the_idea
3

对于这个任务,你不需要使用任何特别的工具或模块。你只需要读取每一行,然后把它们分成一个列表,列表的第一个位置是左边的内容,第二个位置是右边的内容。如果你之后需要这些值,可能可以把它们存储在一个字典里。

这里有一个简单的方法,适合刚接触Python的人。可以取消注释带有print的行,来帮助调试。

f=open("conf.txt","r")
txt=f.read() #all text is in txt
f.close()

fwrite=open("modified.txt","w")
splitedlines = txt.splitlines():
#print splitedlines 
for line in splitedlines:
    #print line
    conf = line.split('=')
    #conf[0] is what it is on left and conf[1] is what it is on right
    #print conf
    if conf[0] == "youget":
        #we get this
        conf[1] = "the_super_idea" #the_idea is now the_super_idea
    #join conf whit '=' and write
    newline = '='.join(conf)
    #print newline
    fwrite.write(newline+"\n")

fwrite.close()

撰写回答