xf3 xf1 xe1 xc3 xad usar u00f3 latinos especiales escribir caracteres python unicode string-formatting

python - xf1 - Cómo controlar el relleno de la cadena Unicode que contiene caracteres del este de Asia



xc3 xad python (4)

Eche un vistazo a la cocina . Creo que podría tener lo que quieres .

Tengo tres picaduras de UTF-8:

hello, world hello, 世界 hello, 世rld

Solo quiero los primeros 10 ascii-char-width para que el soporte en una columna:

[hello, wor] [hello, 世 ] [hello, 世r]

En consola:

width(''世界'')==width(''worl'') width(''世 '')==width(''wor'') #a white space behind ''世''

Un char chino es de tres bytes, pero solo tiene 2 caracteres de ancho cuando se muestra en la consola:

>>> bytes("hello, 世界", encoding=''utf-8'') b''hello, /xe4/xb8/x96/xe7/x95/x8c''

El format() de Python format() no ayuda cuando los caracteres UTF-8 se mezclaron

>>> for s in [''[{0:<{1}.{1}}]''.format(s, 10) for s in [''hello, world'', ''hello, 世界'', ''hello, 世rld'']]: ... print(s) ... [hello, wor] [hello, 世界 ] [hello, 世rl]

No es lindo:

-----------Songs----------- | 1: 蝴蝶 | | 2: 心之城 | | 3: 支持你的爱人 | | 4: 根生的种子 | | 5: 鸽子歌(CUCURRUCUCU PALO| | 6: 林地之间 | | 7: 蓝光 | | 8: 在你眼里 | | 9: 肖邦离别曲 | | 10: 西行( 魔戒王者再临主题曲)(INTO | | X 11: 深陷爱河 | | X 12: 钟爱大地(THE MO RUN AIR | | X 13: 时光流逝 | | X 14: 卡农 | | X 15: 舒伯特小夜曲(SERENADE) | | X 16: 甜蜜的摇篮曲(Sweet Lullaby| ---------------------------

Entonces, me pregunto si hay una manera estándar de hacer el personal de relleno UTF-8.


En primer lugar, parece que estás usando Python 3, así que responderé en consecuencia.

Tal vez no entiendo tu pregunta, pero parece que la salida que recibes es exactamente lo que quieres, excepto que los caracteres chinos son más anchos en tu fuente.

Entonces UTF-8 es una pista falsa, ya que no estamos hablando de bytes , estamos hablando de personajes . Estás en Python 3, por lo que todas las cadenas son Unicode. La representación de bytes subyacente (donde cada uno de esos caracteres chinos está representado por tres bytes) es irrelevante.

Desea recortar o rellenar cada cadena con exactamente 10 caracteres, y eso está funcionando correctamente:

>>> len(''hello, wor'') 10 >>> len(''hello, 世界 '') 10 >>> len(''hello, 世rl'') 10

El único problema es que lo estás mirando con lo que parece ser una fuente monoespaciada, pero que en realidad no lo es . La mayoría de las fuentes monoespaciadas tienen este problema. Todos los caracteres latinos normales tienen exactamente el mismo ancho en esta fuente, pero los caracteres chinos son ligeramente más amplios. Por lo tanto, los tres caracteres "世界 " ocupan más espacio horizontal que los tres caracteres "wor" . No hay mucho que pueda hacer al respecto, además de a) obtener una fuente que sea verdaderamente monoespaciada, ob) calcular con precisión el ancho de cada carácter en la fuente y agregar un número de espacios que lo conduzca aproximadamente a la fuente. misma posición horizontal (esto nunca será preciso).


Al intentar alinear texto ASCII con chino en la fuente de ancho fijo, existe un conjunto de versiones de ancho completo de los caracteres ASCII imprimibles. A continuación hice una tabla de traducción de ASCII a la versión de ancho completo:

# coding: utf8 # full width versions (SPACE is non-contiguous with ! through ~) SPACE = ''/N{IDEOGRAPHIC SPACE}'' EXCLA = ''/N{FULLWIDTH EXCLAMATION MARK}'' TILDE = ''/N{FULLWIDTH TILDE}'' # strings of ASCII and full-width characters (same order) west = ''''.join(chr(i) for i in range(ord('' ''),ord(''~''))) east = SPACE + ''''.join(chr(i) for i in range(ord(EXCLA),ord(TILDE))) # build the translation table full = str.maketrans(west,east) data = ''''''/ 蝴蝶(A song) 心之城(Another song) 支持你的爱人(Yet another song) 根生的种子 鸽子歌(Cucurrucucu palo whatever) 林地之间 蓝光 在你眼里 肖邦离别曲 西行(魔戒王者再临主题曲)(Into something) 深陷爱河 钟爱大地 时光流逝 卡农 舒伯特小夜曲(SERENADE) 甜蜜的摇篮曲(Sweet Lullaby) '''''' # Replace the ASCII characters with full width, and create a song list. data = data.translate(full).rstrip().split(''/n'') # translate each printable line. print('' ----------Songs-----------''.translate(full)) for i,song in enumerate(data): line = ''|{:4}: {:20.20}|''.format(i+1,song) print(line.translate(full)) print('' --------------------------''.translate(full))

Salida

 ----------Songs----------- |   1: 蝴蝶(A song)          | |   2: 心之城(Another song)   | |   3: 支持你的爱人(Yet another s| |   4: 根生的种子               | |   5: 鸽子歌(Cucurrucucu palo| |   6: 林地之间                | |   7: 蓝光                  | |   8: 在你眼里                | |   9: 肖邦离别曲               | |  10: 西行(魔戒王者再临主题曲)(Into s| |  11: 深陷爱河                | |  12: 钟爱大地                | |  13: 时光流逝                | |  14: 卡农                  | |  15: 舒伯特小夜曲(SERENADE)    | |  16: 甜蜜的摇篮曲(Sweet Lullaby|  --------------------------

No es demasiado bonito, pero se alinea.


Parece que no hay soporte oficial para esto, pero un paquete integrado puede ayudar:

>>> import unicodedata >>> print unicodedata.east_asian_width(u''中'')

El valor devuelto representa la categoría del punto de código . Específicamente,

  • W - East Asian Wide
  • F - ancho ancho del este asiático (de estrecho)
  • Na: estrecho de Asia oriental
  • H - Medio ancho del este de Asia (de ancho)
  • A - Asia oriental ambigua
  • N - No asiático oriental

Esta respuesta a una pregunta similar proporcionó una solución rápida. Sin embargo, tenga en cuenta que el resultado de visualización depende de la fuente de monoespaciado exacta utilizada. Las fuentes predeterminadas utilizadas por ipython y pydev no funcionan bien, mientras que la consola de Windows está bien.