所以我之前已经完成了这项工作,这对于看似简单的任务来说是一个令人惊讶的丑陋代码。
目标是将任何不可打印的角色转换为。(点)。出于我的目的,“可打印”会排除string.printable
中的最后几个字符(换行符,制表符等)。这是用于打印旧的MS-DOS调试“十六进制转储”格式......或任何类似的东西(其他空格将破坏预期的转储布局)。
我知道我可以使用string.translate()
,为了使用它,我需要一个翻译表。所以我使用string.maketrans()
。这是我能想到的最好的:
filter = string.maketrans(
string.translate(string.maketrans('',''),
string.maketrans('',''),string.printable[:-5]),
'.'*len(string.translate(string.maketrans('',''),
string.maketrans('',''),string.printable[:-5])))
......这是一个难以理解的混乱(虽然它确实有效)。
从那里你可以使用类似的东西:
for each_line in sometext:
print string.translate(each_line, filter)
......快乐。 (只要你不介意看。)
现在,如果我将这个可怕的表达式分解为单独的语句,它就更具可读性了:
ascii = string.maketrans('','') # The whole ASCII character set
nonprintable = string.translate(ascii, ascii, string.printable[:-5]) # Optional delchars argument
filter = string.maketrans(nonprintable, '.' * len(nonprintable))
为了便于辨认,这样做很诱人。
但是,我一直认为必须有一种更优雅的方式来表达这一点!
答案 0 :(得分:5)
这是使用列表理解的另一种方法:
filter = ''.join([['.', chr(x)][chr(x) in string.printable[:-5]] for x in xrange(256)])
答案 1 :(得分:4)
这里最广泛地使用“ascii”,但你明白了
>>> import string
>>> ascii="".join(map(chr,range(256)))
>>> filter="".join(('.',x)[x in string.printable[:-5]] for x in ascii)
>>> ascii.translate(filter)
'................................ !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~.................................................................................................................................'
如果我打高尔夫球,可能会使用这样的东西:
filter='.'*32+"".join(map(chr,range(32,127)))+'.'*129
答案 2 :(得分:1)
对于实际的代码 - 高尔夫,我想你完全避免使用string.maketrans
s=set(string.printable[:-5])
newstring = ''.join(x for x in oldstring if x in s else '.')
或
newstring=re.sub('[^'+string.printable[:-5]+']','',oldstring)
答案 3 :(得分:1)
我觉得这个解决方案很难看。它肯定比任何基于正则表达式的解决方案更有效。这是一个更短的解决方案。但只适用于python2.6:
nonprintable = string.maketrans('','').translate(None, string.printable[:-5])
filter = string.maketrans(nonprintable, '.' * len(nonprintable))