猿问

我该如何处理这些奇怪的特殊字符弄乱了我的打印格式?

我正在打印一个格式化的表格。但有时这些用户生成的字符会占用不止一个字符的宽度,并且会弄乱格式,正如您在下面的屏幕截图中看到的那样......

“标题”列的宽度被格式化为 68 字节。但是这些“特殊字符”占用了超过 1 个字符的宽度,但仅计为 1 个字符。这会将列推过其边界。


print('{0:16s}{3:<18s}{1:68s}{2:>8n}'.format((

    ' ' + streamer['user_name'][:12] + '..') if len(streamer['user_name']) > 12 else ' ' + streamer['user_name'],

    (streamer['title'].strip()[:62] + '..') if len(streamer['title']) > 62 else streamer['title'].strip(),

    streamer['viewer_count'],

    (gamesDic[streamer['game_id']][:15] + '..') if len(gamesDic[streamer['game_id']]) > 15 else gamesDic[streamer['game_id']]))

关于如何处理这些特殊字符的任何建议?


编辑: 我将有问题的字符串打印到文件中。


🔴𝐀𝐒𝐌𝐑 (𝙪𝙥 𝙘𝙡𝙤𝙨𝙚) ✨ LIVE 🔔 SUBS GET SNAPCHAT


编辑2:


为什么这些不在字符边界上对齐?

http://img.mukewang.com/619350f700012e4005730038.jpg

杨魅力
浏览 193回答 2
2回答

跃然一笑

我对这个问题发表了以下评论:“LIVE”中的字符为全角字符。一种处理它们的hacky方法可能是测试它们的宽度&nbsp;unicodedata.east_asian_width(char)(对于全角字符它将返回“F”)并替换为的最后一个字符&nbsp;unicodedata.name(char)(或仅将它们计为长度2)这个“答案”本质上是另一个评论,但对于评论字段来说太长了。这个 hack - 在 Alderven 的回答中实现- 几乎适用于 OP,但示例字符串以额外的半个字符宽度呈现(注意示例字符串不包含任何东亚半角字符。)。我无法使用此测试语句重现此确切行为,s问题中的示例字符串在哪里,更改删除的字符:print((s&nbsp;+&nbsp;(68&nbsp;-&nbsp;(len(s)&nbsp;+&nbsp;sum(1&nbsp;for&nbsp;x&nbsp;in&nbsp;s&nbsp;if&nbsp;ud.east_asian_width(x)&nbsp;in&nbsp;('F',&nbsp;'N',&nbsp;'W'))))&nbsp;*&nbsp;'x')+&nbsp;'\n'+&nbsp;('x'&nbsp;*&nbsp;68))在 Debian 的 Gnome 终端中的 Python 3.6 解释器中,使用默认的等宽常规字体,删除全角字符会导致示例字符串明显比等效的 "x" 字符串长三个字符。删除全角和宽(东亚宽度“W”)字符生成的字符串似乎呈现与等效数量的“x”相同的长度。在 OpenSuse 上的 Python 3.7 KDE Konsole 终端中,使用 Ubuntu Monospace 常规字体,我无法生成呈现相同长度的字符串,无论我删除了全角、宽角或中性 (“N”) 字符的组合如何。我确实注意到,在 Konsole 中单独渲染时,火花字符 (✨) 似乎占用了额外的半宽,但在测试完整字符串时看不到任何半宽差异。我怀疑问题出在 Python 控制之外的低级渲染,正如关于 Unicode标准的这个注释所暗示的那样:注意:&nbsp;East_Asian_Width 属性不适用于现代终端仿真器,而无需根据具体情况进行适当调整。此类终端仿真器需要一种方法来解决此类环境所需的半角/全角二分法,但 East_Asian_Width 属性并未为所有情况提供现成的解决方案。Unicode 标准不断增长的曲目早已超出了东亚传统字符编码的范围,终端仿真通常需要定制以支持边缘情况和随着时间的推移排版行为的变化。

梦里花落0921

我已经根据@snakecharmerb 的评论编写了自定义字符串格式化程序,但仍然存在“半字符宽度”问题:import unicodedatadef fstring(string, max_length, align='l'):&nbsp; &nbsp; string = str(string)&nbsp; &nbsp; extra_length = 0&nbsp; &nbsp; for char in string:&nbsp; &nbsp; &nbsp; &nbsp; if unicodedata.east_asian_width(char) == 'F':&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; extra_length += 1&nbsp; &nbsp; diff = max_length - len(string) - extra_length&nbsp; &nbsp; if diff > 0:&nbsp; &nbsp; &nbsp; &nbsp; return string + diff * ' ' if align == 'l' else diff * ' ' + string&nbsp; &nbsp; elif diff < 0:&nbsp; &nbsp; &nbsp; &nbsp; return string[:max_length-3] + '.. '&nbsp; &nbsp; return stringdata = [{'user_name': 'shroud', 'game_id': 'Apex Legends', 'title': 'pathfinder twitch prime loot YAYA @shroud on socials for update', 'viewer_count': 66200},&nbsp; &nbsp; &nbsp; &nbsp; {'user_name': 'Amouranth', 'game_id': 'ASMR', 'title': '🔴 𝐀𝐒𝐌𝐑 (𝙪𝙥 𝙘𝙡𝙤𝙨𝙚) ✨ LIVE 🔔 SUBS GET SNAPCHAT', 'viewer_count': 2261}]for d in data:&nbsp; &nbsp; name = fstring(d['user_name'], 20)&nbsp; &nbsp; game_id = fstring(d['game_id'], 15)&nbsp; &nbsp; title = fstring(d['title'], 62)&nbsp; &nbsp; count = fstring(d['viewer_count'], 10, align='r')&nbsp; &nbsp; print('{}{}{}{}'.format(name, game_id, title, count))它产生输出:
随时随地看视频慕课网APP

相关分类

Python
我要回答