使用 string.translate() 将不可打印的字符修改为点

发布于 2024-08-13 07:41:40 字数 1124 浏览 1 评论 0原文

所以我以前就做过这样的事情,对于这样一个看似简单的任务来说,这是一段令人惊讶的丑陋的代码。

目标是将任何不可打印的字符转换为 .(点)。出于我的目的,“printable”确实排除了 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))

并且为了易读性而这样做很诱人。

然而,我一直认为必须有一种更优雅的方式来表达这一点!

So I've done this before and it's a surprising ugly bit of code for such a seemingly simple task.

The goal is to translate any non-printable character into a . (dot). For my purposes "printable" does exclude the last few characters from string.printable (new-lines, tabs, and so on). This is for printing things like the old MS-DOS debug "hex dump" format ... or anything similar to that (where additional whitespace will mangle the intended dump layout).

I know I can use string.translate() and, to use that, I need a translation table. So I use string.maketrans() for that. Here's the best I could come up with:

filter = string.maketrans(
   string.translate(string.maketrans('',''),
   string.maketrans('',''),string.printable[:-5]),
   '.'*len(string.translate(string.maketrans('',''),
   string.maketrans('',''),string.printable[:-5])))

... which is an unreadable mess (though it does work).

From there you can call use something like:

for each_line in sometext:
    print string.translate(each_line, filter)

... and be happy. (So long as you don't look under the hood).

Now it is more readable if I break that horrid expression into separate statements:

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))

And it's tempting to do that just for legibility.

However, I keep thinking there has to be a more elegant way to express this!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

岁月蹉跎了容颜 2024-08-20 07:41:40

这是使用列表理解的另一种方法:

filter = ''.join([['.', chr(x)][chr(x) in string.printable[:-5]] for x in xrange(256)])

Here's another approach using a list comprehension:

filter = ''.join([['.', chr(x)][chr(x) in string.printable[:-5]] for x in xrange(256)])
顾铮苏瑾 2024-08-20 07:41:40

这里最广泛使用的是“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

Broadest use of "ascii" here, but you get the idea

>>> 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{|}~.................................................................................................................................'

If I were golfing, probably use something like this:

filter='.'*32+"".join(map(chr,range(32,127)))+'.'*129
木緿 2024-08-20 07:41:40

对于实际的代码高尔夫,我想你会完全避免 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)

for actual code-golf, I imagine you'd avoid string.maketrans entirely

s=set(string.printable[:-5])
newstring = ''.join(x for x in oldstring if x in s else '.')

or

newstring=re.sub('[^'+string.printable[:-5]+']','',oldstring)
朮生 2024-08-20 07:41:40

我不觉得这个解决方案丑陋。它肯定比任何基于正则表达式的解决方案更有效。这是一个稍微短一点的解决方案。但仅适用于python2.6:

nonprintable = string.maketrans('','').translate(None, string.printable[:-5])
filter = string.maketrans(nonprintable, '.' * len(nonprintable))

I don't find this solution ugly. It is certainly more efficient than any regex based solution. Here is a tiny bit shorter solution. But only works in python2.6:

nonprintable = string.maketrans('','').translate(None, string.printable[:-5])
filter = string.maketrans(nonprintable, '.' * len(nonprintable))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文