我有一個非常漫長而艱難的時間來管理寫了下面的代碼。
我很難用逗號來管理。我希望更新後的文件在更新之前具有與要更新的文件相同的格式,然後更新:行以逗號結尾,但最後一個除外。
此代碼是針對提問者公開的特定問題而製作的,無法按原樣用於其他類型的問題。我知道。這是使用基於正則表達式而不是解析器的代碼的問題,我完全意識到這一點。但我認爲這是一個可以相對容易地適應其他情況的畫布,通過改變正則表達式,由於正則表達式的可展性,這是一個相對容易的過程。
def file_updating(updating_filename,updating_data_extractor,filename_to_update):
# function whose name is hold by updating_data_extractor parameter
# is a function that
# extracts data from the file whose name is hold by updating_filename parameter
# and must return a tuple:
# (updating dictionary , compiled regex)
updating_dico,pat = updating_data_extractor(updating_filename)
with open(filename_to_update,'r+') as f:
lines = f.readlines()
def jiji(line,dico = updating_dico):
mat = pat.search(line.rstrip())
if mat and mat.group(3) in dico:
return '%s: %s,' % (mat.group(1),dico.pop(mat.group(3)))
else:
return line.rstrip(',') + ','
li = [jiji(line) for line in lines[0:-1] ] # [0:-1] because last line is '}'
front = (mit.group(2) for mit in (pat.search(line) for line in lines) if mit).next()
li.extend(front + '%s: %s,' % item for item in updating_dico.iteritems())
li[-1] = li[-1].rstrip(',')
li.append('}')
f.seek(0,0)
f.writelines('\n'.join(li) )
f.truncate()
例證代碼:
import re
bef1 = '''#comments
config =
{
#comments
'name': 'hello',
'arctic':01011101,
'summu': 456,
'see?': 'world',
'armorique': 'bretagne'
}'''
bef2 = '''#comments
config =
{
#comments
'name': 'abc',
'see?': { 'world':'india':'jagdev'},
}'''
def one_extractor(data_containing_filename):
with open(data_containing_filename) as g:
contg = re.search('\[(\d+)\].+\[config\](.*?)\[(\\1)\]',g.read(),re.DOTALL)
if contg:
updtgen = (re.match("([^=]+)=[ \f\t\v]*([^ \f\t\v].*|)",line.strip())
for line in contg.group(2).splitlines())
updating_data = dict(mi.groups() for mi in updtgen if mi and mi.group(2))
else:
from sys import exit
exit(updating_filename + " isn't a valid file for updating")
pat = re.compile("(([ \t]*)([^:]+)):\s*(.+),?")
return (updating_data,pat)
for bef in (bef1,bef2):
# file to update: rudu.txt
with open('rudu.txt','w') as jecr:
jecr.write(bef)
# updating data: renew_rudu.txt
with open('renew_rudu.txt','w') as jecr:
jecr.write('''[23]
[config]
'nuclear'= 'apocalypse'
'name'='abc'
'armorique'= 'BRETAGNE'
'arctic'=
'boloni'=7600
'see?'=
'summu'='tumulus'
[23]''')
print 'BEFORE ---------------------------------'
with open('rudu.txt') as lir:
print lir.read()
print '\nUPDATING DATA --------------------------'
with open('renew_rudu.txt') as lir:
print lir.read()
file_updating('renew_rudu.txt',one_extractor,'rudu.txt')
print '\nAFTER ================================='
with open('rudu.txt','r') as f:
print f.read()
print '\n\nX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#\n'
結果:
>>>
BEFORE ---------------------------------
#comments
config =
{
#comments
'name': 'hello',
'arctic':01011101,
'summu': 456,
'see?': 'world',
'armorique': 'bretagne'
}
UPDATING DATA --------------------------
[23]
[config]
'nuclear'= 'apocalypse'
'name'='abc'
'armorique'= 'BRETAGNE'
'arctic'=
'boloni'=7600
'see?'=
'summu'='tumulus'
[23]
AFTER =================================
#comments,
config =,
{,
#comments,
'name': 'abc',
'arctic':01011101,
'summu': 'tumulus',
'see?': 'world',
'armorique': 'BRETAGNE',
'boloni': 7600,
'nuclear': 'apocalypse'
}
X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#
BEFORE ---------------------------------
#comments
config =
{
#comments
'name': 'abc',
'see?': { 'world':'india':'jagdev'},
}
UPDATING DATA --------------------------
[23]
[config]
'nuclear'= 'apocalypse'
'name'='abc'
'armorique'= 'BRETAGNE'
'arctic'=
'boloni'=7600
'see?'=
'summu'='tumulus'
[23]
AFTER =================================
#comments,
config =,
{,
#comments,
'name': 'abc',
'see?': { 'world':'india':'jagdev'},
'armorique': 'BRETAGNE',
'boloni': 7600,
'summu': 'tumulus',
'nuclear': 'apocalypse'
}
X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#
>>>
。
編輯:
我提高了代碼,因爲我還在insatisfied。現在,「變量」前面的在要更新的文件中包含數據的行的開始處捕獲空白字符(' '
或'\t'
)。
我也忘記了指令f.truncate()
這是非常重要的不保留不需要的字符的尾巴。
我很滿意地看到,我的代碼工作良好,即使具有下列文件中的值是一個dictionnary,所呈現的Jagdev:
#comments
config =
{
#comments
'name': 'abc',
'see?': { 'world':'india':'jagdev'},
}
這證實了我在我的選擇,工藝路線行後,而不是試圖用正則表達式運行整個文件。
。
編輯2:
我再次更改了代碼。該更新是通過使用帶作爲參數的函數來執行:
因此,可以使用來自各種更新文件的數據來更新給定文件。這使得代碼更通用。
第一個你實際上可以導入並使用「配置」之後。對於第二種類型,你可能需要編寫一個小解析器,如果你從來沒有做過,那麼這是一項艱鉅的任務,但如果你知道該怎麼做,這是一個相當容易的任務。取決於你有多少時間應該認真考慮用這個例子學習解析器。它是每個編碼器庫中的重要武器。我甚至會說,如果沒有這個技能,你幾乎可以自稱自己的編碼器。 – erikbwork 2011-03-15 13:57:06
無需編寫解析器,python包含電池:[configparser](http://docs.python.org/library/configparser.html)cc @erikb – 2011-03-15 14:02:30
configparser無法工作,因爲鍵/值對是被'-chars包圍。可能的逗號也會造成嚴重破壞...... – 2011-03-15 15:11:36