Python 未知模式查找
好的,简单来说,我想通过重用代码来压缩一个文件,然后在运行时替换缺失的代码。我现在的做法很丑陋而且速度慢,虽然至少能用。问题是这个文件没有特定的结构,比如'aGVsbG8=\n',这是一个base64编码的例子。我的函数速度很慢,因为文件长度超过1700,而且它是逐个字符检查模式的。请帮我提供一些更好的代码,或者至少帮我优化一下我现有的代码。任何有帮助的建议都很欢迎!顺便说一下,我已经尝试过压缩库,但它们的压缩效果没有我这个丑陋的函数好。
def c_long(inp, cap=False, b=5):
import re,string
if cap is False: cap = len(inp)
es = re.escape; le=len; ref = re.findall; ran = range; fi = string.find
c = b;inpc = inp;pattern = inpc[:b]; l=[]
rep = string.replace; ins = list.insert
while True:
if c == le(inpc) and le(inpc) > b+1: c = b; inpc = inpc[1:]; pattern = inpc[:b]
elif le(inpc) <= b: break
if c == cap: c = b; inpc = inpc[1:]; pattern = inpc[:b]
p = ref(es(pattern),inp)
pattern += inpc[c]
if le(p) > 1 and le(pattern) >= b+1:
if l == []: l = [[pattern,le(p)+le(pattern)]]
elif le(ref(es(inpc[:c+2]),inp))+le(inpc[:c+2]) < le(p)+le(pattern):
x = [pattern,le(p)+le(inpc[:c+1])]
for i in ran(le(l)):
if x[1] >= l[i][1] and x[0][:-1] not in l[i][0]: ins(l,i,x); break
elif x[1] >= l[i][1] and x[0][:-1] in l[i][0]: l[i] = x; break
inpc = inpc[:fi(inpc,x[0])] + inpc[le(x[0]):]
pattern = inpc[:b]
c = b-1
c += 1
d = {}; c = 0
s = ran(le(l))
for x in l: inp = rep(inp,x[0],'{%d}' % s[c]); d[str(s[c])] = x[0]; c += 1
return [inp,d]
def decompress(inp,l): return apply(inp.format, [l[str(x)] for x in sorted([int(x) for x in l.keys()])])
2 个回答
通常情况下,人们会先把程序通过一个专门为文本优化的压缩算法进行压缩,然后再用 exec
来执行它,比如:
code="""..."""
exec(somelib.decompress(code), globals=???, locals=???)
可能 .pyc
或 .pyo
文件已经被压缩过了。你可以通过创建一个简单的文件来检查,比如用 x="""aaaaaaaa"""
,然后逐渐增加长度,比如 x="""aaaaaaaaaaaaaaaaaaaaaaa...aaaa"""
,看看文件大小是否有明显变化。
压缩经过Base64编码的数据最简单的方法是先把它转换成二进制数据,这样就能节省大约25%的存储空间:
>>> s = "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=\n"
>>> t = s.decode("base64")
>>> len(s)
37
>>> len(t)
26
在大多数情况下,你还可以使用一些压缩算法进一步压缩这个字符串,比如用 t.encode("bz2")
或者 t.encode("zlib")
。
关于你的代码,有几点需要注意:有很多因素让代码看起来不太好,比如空格不一致、行太长、变量名没有意义、代码风格不规范等等。举个例子:你的 decompress()
函数可以写得更简单明了:
def decompress(compressed_string, substitutions):
subst_list = [substitutions[k] for k in sorted(substitutions, key=int)]
return compressed_string.format(*subst_list)
这样一来,代码的功能就更清楚了。你还可以再进一步:为什么 substitutions
是一个用字符串作为键的字典,比如 "0"
、"1"
等等?用字符串而不是整数其实很奇怪,而且你根本不需要这些键!用一个简单的列表就可以了,decompress()
也会变得更简单:
def decompress(compressed_string, substitutions):
return compressed_string.format(*substitutions)
你可能觉得这些都是小问题,但如果你把其他代码也写得同样清晰,你就能自己发现代码中的错误。(确实有错误——它在处理 "abcdefgabcdefg"
和很多其他字符串时会崩溃。)