Saltar al contenido

Visualización de Unicode en Powershell

Solución:

Nota: con respecto a Comandos de PowerShell por sí solo, solo importa la elección de la fuente, suponiendo que los archivos de código fuente estén codificados correctamente; con respecto a programas externos, $OutputEncoding, [Console]::InputEncoding y [Console]::OutputEncoding también importa.


los Potencia Shell Centro (v6 +) perspectiva (consulte la siguiente sección para Windows PowerShell), independientemente de su carácter representación problemas (también cubiertos en la siguiente sección), con respecto a la comunicación con programas externos:

  • Sobre Unix-como plataformas, PowerShell Core es Compatible con UTF-8 por defecto (normalmente, en estos días, dado que las plataformas modernas tipo Unix usan configuraciones regionales basadas en UTF-8).

  • Sobre Ventanas, es el legado configuración regional del sistema, a través de su Página de códigos OEM, que determina la codificación predeterminada en todas las consolas, incluidas las ventanas de consola Windows PowerShell y PowerShell Core, aunque las versiones recientes de Windows 10 ahora permiten configurar la configuración regional del sistema en la página de códigos 65001 (UTF-8) (la función aún está en versión beta a partir de la versión 1909 de Windows 10).

    • Si usa esa función, PowerShell Centro las ventanas de la consola serán automáticamente compatibles con UTF-8, aunque en Windows PowerShell todavía tendrás que configurar $OutputEncoding a UTF-8 también (que en Core ya está predeterminado en UTF-8), como se muestra a continuación.

    • De lo contrario, especialmente en versiones anteriores de Windows, puede utilizar el mismo enfoque que se detalla a continuación para Windows PowerShell.


Haciendo tu Windows PowerShell ventana de consola compatible con Unicode (UTF-8):

  • Elige un Tipo verdadero (TT) fuente que apoya el especifico guiones (sistemas de escritura, alfabetos) cuyos caracteres desea mostrar correctamente en la consola:

    • Importante: Tiempo todas las fuentes TrueType son compatibles con Unicode en principio, ellos Por lo general, solo admite un subconjunto de todos los caracteres Unicode, es decir, los correspondientes a guiones (sistemas de escritura), como la escritura latina, la escritura cirílica (rusa), …
      En su caso particular, si debe admitir caracteres árabes, chinos, japoneses y rusos, su única opción es SimSun-ExtB, que está disponible en Solo Windows 10.
      Consulte Wikipedia para obtener una lista de las fuentes de Windows destinadas a qué scripts (alfabetos).

    • Para cambiar la fuente, haga clic en el icono en la esquina superior izquierda de la ventana y seleccione Properties, luego cambie al Fonts pestaña y seleccione la fuente TrueType que le interese.

      • Vea esta respuesta SU de not2quibit para saber cómo hacer que las fuentes adicionales estén disponibles.
  • Además, para una comunicación adecuada con programas externos:

    • los la página de códigos de la ventana de la consola debe cambiarse a 65001, la página de códigos UTF-8 (que generalmente se hace con chcp 65001, que, sin embargo, no se puede usar directamente desde una sesión de PowerShell[1], pero el siguiente comando de PowerShell tiene el mismo efecto).

    • Se debe indicar a Windows PowerShell que use UTF-8 para comunicarse con utilidades externas también, tanto al enviar entrada de canalización para programas externos, a través de él $OutputEncoding variable de preferencia (al decodificar la salida de programas externos, es la codificación almacenada en [console]::OutputEncoding que se aplica).

El siguiente encantamiento mágico en Windows PowerShell hace esto (como se indicó, este implícitamente realiza chcp 65001):

$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding =
                    New-Object System.Text.UTF8Encoding

Para persistir estos ajustes, es decir, para que sus futuras sesiones interactivas de PowerShell sean compatibles con UTF-8 de forma predeterminada, agregue el comando anterior a su $PROFILE expediente.

Nota: Las versiones recientes de Windows 10 ahora permiten configurar el configuración regional del sistema a la página de códigos 65001 (UTF-8) (la función todavía está en beta a partir de la versión 1903 de Windows 10), lo que hace todos Las ventanas de la consola están predeterminadas en UTF-8, incluido Windows PowerShell.
Si usa esa función, la configuración [console]::InputEncoding / [console]::OutputEncoding entonces ya no es estrictamente necesario, pero aún tendrá que configurar $OutputEncoding (que no es necesario en PowerShell Centro, dónde $OutputEncoding ya está predeterminado en UTF-8).

Importante:

  • Estas La configuración asume que las utilidades externas con las que se comunica esperan una entrada codificada en UTF-8 y producen una salida UTF-8..

    • Las CLI escritas en Node.js cumplen ese criterio, por ejemplo.
    • Los scripts de Python, si se escriben teniendo en cuenta la compatibilidad con UTF-8, también pueden manejar UTF-8.
  • Por el contrario, estos ajustes pueden rotura utilidades (más antiguas) que solo esperan una codificación de un solo byte como lo implica la página de códigos OEM heredada del sistema.

    • Hasta Windows 8.1, esto incluso incluía utilidades estándar de Windows como find.exe y findstr.exe, que se han corregido en Windows 10.
    • Consulte la parte inferior de esta publicación para saber cómo evitar este problema cambiando a UTF-8 temporalmente, bajo demanda para invocar una utilidad determinada.
  • Esta configuración se aplica a solo programas externos y no están relacionados con las codificaciones que Cmdlets de PowerShell usar en la salida:

    • Consulte esta respuesta para conocer las codificaciones de caracteres predeterminadas que utilizan los cmdlets de PowerShell; en resumen: si quieres cmdlets en Windows PowerShell por defecto a UTF-8 (que Potencia Shell [Core] v6 + lo hace de todos modos), agregue $PSDefaultParameterValues['*:Encoding'] = 'utf8' para usted $PROFILE, pero tenga en cuenta que esto afectará a todas las llamadas a cmdlets con un -Encoding parámetro en sus sesiones, a menos que ese parámetro se use explícitamente; también tenga en cuenta que en Windows PowerShell invariablemente obtendrá archivos UTF-8 con BOM; a la inversa, en Potencia Shell [Core] v6 +, que por defecto es BOM-menos UTF-8 (ambos en ausencia de -Encoding y con -Encoding utf8, tendrías que usar 'utf8BOM'.

Información de antecedentes opcional

Punta del sombrero a eryksun por todas sus aportaciones.

  • Mientras una fuente TrueType está activa, la ventana de la consola buffer conserva correctamente (no ASCII) caracteres Unicode. incluso si no lo hacen hacer correctamente; es decir, aunque puedan aparecer genéricamente como ?, para indicar la falta de compatibilidad con la fuente actual, puede copiar pegar tales personajes en otros lugares sin pérdida de información, como señala eryksun.

  • PowerShell es capaz de generar caracteres Unicode a la consola incluso sin haber cambiado a la página de códigos 65001 primero.
    Sin embargo, eso por sí mismo no Garantice que otros programas puedan manejar dicha salida correctamente; consulte a continuación.

  • Cuando se trata de comunicándose con programas externos vía stdout (tubería), PowersShell utiliza la codificación de caracteres especificada en el $OutputEncoding variable de preferencia, cuales por defecto es ASCII (!) en Windows PowerShell, lo que significa que todos los caracteres que no sean ASCII se transcriben a literal? personajes, resultando en pérdida de información. (Por el contrario, de manera encomiable, PowerShell Centro (v6 +) ahora usa (sin BOM) UTF-8 como la codificación predeterminada, de manera consistente).

    • Por el contrario, sin embargo, pasando no ASCII argumentos (en lugar de salida estándar (canalizada)) a programas externos parece requerir no configuración especial (no me queda claro por qué funciona); por ejemplo, el siguiente comando de Node.js devuelve correctamente €: 1 incluso con la configuración predeterminada:
      node -pe "process.argv[1] + ': ' + process.argv[1].length" €
  • [Console]::OutputEncoding:

    • controla qué codificación de caracteres se asume cuando la consola traduce la salida del programa en caracteres de visualización de la consola.
    • además dice Potencia Shell qué codificación asumir cuando captura de salida de un programa externo.
      El resultado es que si necesitas captura de salida desde un programa de producción de UTF-8, debe configurar [Console]::OutputEncoding a UTF-8 también; configuración $OutputEncoding solo cubre el aporte (al programa externo) aspecto.
  • [Console]::InputEncoding establece la codificación para entrada de teclado en una consola[2] y también determina cómo la CLI de PowerShell interpreta los datos que recibe a través de stdin (entrada estándar).

  • Si cambia la consola a UTF-8 para sesión completa no es una opción, puedes hacerlo temporalmente, para una llamada determinada:

      # Save the current settings and temporarily switch to UTF-8.
      $oldOutputEncoding = $OutputEncoding; $oldConsoleEncoding = [Console]::OutputEncoding
      $OutputEncoding = [Console]::OutputEncoding = New-Object System.Text.Utf8Encoding
    
      # Call the UTF-8 program, using Node.js as an example.
      # This should echo '€' (`U+20AC`) as-is and report the length as *1*.
      $captured = '€' | node -pe "require('fs').readFileSync(0).toString().trim()"
      $captured; $captured.Length
    
      # Restore the previous settings.
      $OutputEncoding = $oldOutputEncoding; [Console]::OutputEncoding = $oldConsoleEncoding
    
  • Problemas en versiones anteriores de Windows (anteriores a W10):

    • Un activo chcp valor de 65001 romper la salida de la consola de algunos programas externos e incluso los archivos por lotes en general en versiones anteriores de Windows puede, en última instancia, deberse a un error en el WriteFile() Función de la API de Windows (como también la usa la biblioteca C estándar), que informó erróneamente el número de caracteres en vez de bytes con página de códigos 65001 en efecto, como se discutió en esta publicación de blog.
  • Los síntomas resultantes, según un comentario de bobince sobre esta respuesta de 2008, son: “Tengo entendido que las llamadas que devuelven un número de bytes (como fread / fwrite / etc) en realidad devuelven un número de caracteres. Esto provoca una amplia una variedad de síntomas, como lectura de entrada incompleta, bloqueos, archivos por lotes rotos, etc. “


Alternativas superiores a la consola nativa de Windows (terminal), conhost.exe

eryksun sugiere dos alternativas a las ventanas nativas de la consola de Windows (conhost.exe), que proveedor carácter Unicode mejor y más rápido representación, debido al uso de la moderna API DirectWrite / DirectX acelerada por GPU en lugar de la “antigua implementación de GDI [that] no puede manejar scripts complejos, caracteres que no son BMP o fuentes de respaldo automáticas “.

  • El próximo, de código abierto de Microsoft Terminal de Windows, que se distribuirá y actualizará a través de Microsoft Store en Windows 10; consulte aquí para obtener una introducción.

  • Alternativa de terceros establecida desde hace mucho tiempo ConEmu, que tiene la ventaja de funcionar también en versiones anteriores de Windows.


[1] Tenga en cuenta que correr chcp 65001 de dentro una sesión de PowerShell es no eficaz, porque .NET cachés la codificación de salida de la consola en el inicio y desconoce los cambios posteriores realizados con chcp (solo cambios realizados directamente a través de [console]::OutputEncoding] son recogidos).

[2] No tengo claro cómo se manifiesta eso en la práctica; díganos, si sabe.

Elaboró ​​la respuesta de Alexander Martin. Para propósitos de prueba, he creado algunas carpetas y archivos con nombres válidos de diferentes subrangos Unicode de la siguiente manera:

nombres validos

Por ejemplo, con Courier Nuevo fuente de la consola, los símbolos de reemplazo se muestran en lugar de los caracteres CJK en una consola PowerShell:

Courier Nuevo

Por otro lado, con SimSun fuente de la consola, los símbolos de reemplazo (poco visibles) se muestran en lugar de los caracteres árabes y hebreos, mientras que los caracteres CJK parecen mostrarse correctamente:

SimSun

Tenga en cuenta que todos los símbolos de reemplazo son simplemente desplegado mientras que los personajes reales se conservan como puede ver en el siguiente Copiar pegar desde arriba de la consola de PowerShell:

PS D:PShell> (Get-ChildItem 'D:batUnASCII Names' -Dir).Name
Arabic (عَرَبِيّ‎)
CJK (中文(繁體))
Czech (Čeština)
Greek (Γρεεκ)
Hebrew (עִבְרִית)
Japanese (日本語)
MathBoldScript ()
Russian (русский язык)
Türkçe (Türkiye)
‹angles›
☺☻♥♦

En aras de la integridad, estos son los valores de registro apropiados para habilitar más fuentes para el símbolo del sistema de Windows (esto también funciona para la consola de Windows PowerShell):

(Get-ItemProperty 'HKLM:SOFTWAREMicrosoftWindows NTCurrentVersionConsoleTrueTypeFont' |
    Select-Object -Property [0-9]* | Out-String).Split( 
        [System.Environment]::NewLine, 
        [System.StringSplitOptions]::RemoveEmptyEntries) | 
     Sort-Object

Salida de muestra:

0       : Consolas
00      : Source Code Pro
000     : DejaVu Sans Mono
0000    : Courier New
00000   : Simplified Arabic Fixed
000000  : Unifont
0000000 : Lucida Console
932     : *MS ゴシック
936     : *新宋体

Comentarios y valoraciones

Si tienes alguna sospecha o capacidad de acrecentar nuestro tutorial puedes añadir una crónica y con gusto lo interpretaremos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *