在Powershell中显示Unicode

Dhi*_*mar 25 unicode terminal powershell utf-8 windows-console

虽然Powershell几乎不可能实现,但我想要实现的目标却相当简单.

我想显示文件的完整路径,其中一些文件的名称中包含阿拉伯语,中文,日语和俄语字符

我总是得到一些难以理解的输出,如下图所示 在此输入图像描述

在控制台中看到的输出正在被另一个脚本消耗.输出包含而不是实际的人物.

执行的命令是

(Get-ChildItem -Recurse -Path "D:\test" -Include *unicode* | Get-ChildItem -Recurse).FullName
Run Code Online (Sandbox Code Playgroud)

是否有任何简单的方法来启动PowerShell(通过命令行或以任何方式写入脚本),以便正确地看到输出.

PS我在Stack Overflow上经历了很多类似的问题,但除了称之为Windows控制台子系统问题之外,它们都没有太多的输入.

mkl*_*nt0 44

请注意,类似Unix的平台上的PowerShell Core终端窗口默认情况下UTF-8感知(通常,现在,鉴于现代类Unix平台使用基于UTF-8的语言环境). 在Windows上,从PowerShell Core 6.2.0-preview.3开始还不是这样,但应尽快实现 - 请参阅此GitHub问题

使您的Windows PowerShell控制台窗口符合Unicode(UTF-8):

  • 选择一个TrueType(TT)字体,该字体支持要在控制台中正确显示其特征的特定脚本(编写系统,字母):

    • 重要提示:虽然所有的TrueType字体支持Unicode 原则,它们通常只支持一个子集的所有Unicode字符,即那些对应于特定的脚本(书写系统),如拉丁字母,斯拉夫(俄罗斯)脚本,...
      在您的特殊情况 - 如果您必须支持阿拉伯语以及中文,日语和俄语字符 - 您唯一的选择是65001,仅适用于Windows 10.
      有关Windows字体针对哪些脚本(字母表)的列表,请参阅Wikipedia.

    • 要更改字体,请单击窗口左上角的图标并选择$OutputEncoding,然后切换到SimSun-ExtB选项卡并选择感兴趣的TrueType字体.

  • 另外:

    • 控制台窗口的代码页必须切换到Properties时,UTF-8代码页(通常有做Fonts,但下面的PowerShell命令不隐式).

    • 发送输入接收输出,必须指示PowerShell使用UTF-8与外部实用程序通信.

Windows PowerShell中的以下魔术咒语执行此操作(如上所述,这隐式执行65001):

$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding =
                    New-Object System.Text.UTF8Encoding
Run Code Online (Sandbox Code Playgroud)

保留这些设置,即默认情况下使您的未来交互式PowerShell会话以UTF-8识别,请将上面的命令添加到您的chcp 65001文件中.

重要:

  • 这些设置假定您与之通信的任何外部实用程序都需要UTF-8编码的输入并生成UTF-8输出.
    • 例如,用Node.js编写的CLI符合该标准.
    • Python脚本 - 如果用UTF-8支持编写 - 也可以处理UTF-8.
  • 相比之下,这些设置可能会破坏(较旧的)实用程序,这些实用程序只需要系统的传统OEM代码页所暗示的单字节编码.
    • 在Windows 8.1中,这甚至包括标准的Windows实用程序,如$OutputEncoding[console]::OutputEncoding,已在Windows 10中修复.
    • 请参阅本文的底部,了解如何根据需要临时切换到UTF-8来绕过此问题,以便调用给定的实用程序.

可选的背景信息

eryksun的帽子提示他的所有输入.

  • 当TrueType字体处于活动状态时,控制台窗口缓冲区正确保留(非ASCII)Unicode字符.即使它们没有正确呈现 ; 也就是说,尽管它们可能看起来一般chcp 65001表示当前字体缺乏支持,但您可以在不丢失信息的情况下将这些字符复制并粘贴到其他地方,正如eryksun所观察到的那样.

  • 即使没有先切换到代码页,PowerShell也能够将Unicode字符输出到控制台$PROFILE.
    但是,这本身并不能保证其他程序能够正确处理这样的输出 - 见下文.

  • 通过stdout(管道)外部程序通信时,它使用65001首选项变量中指定的字符编码,在Windows PowerShell中默认为ASCII(!),这意味着任何非ASCII字符都被音译为文字 [console]::InputEncoding字符,导致信息丢失.(相比之下,值得称道的是,PowerShell Core现在使用(无BOM)UTF-8作为默认编码,无处不在.)

    • 相比之下,然而,通过非ASCII 参数(而不是标准输出(管道)输出)到外部程序似乎需要特殊配置(目前还不清楚我为什么,工程); 例如,[console]::OutputEncoding即使使用默认配置,以下Node.js命令也会正确返回:
      $OutputEncoding
  • $OutputEncoding:

    • 控制在控制台将程序输出转换为控制台显示字符时控制的字符编码.
    • 告诉PowerShell从外部程序捕获输出时要采用的编码方式.
      结果是,如果你需要从产生UTF-8的程序中捕获输出,你需要设置find.exe为UTF-8; 设置findstr.exe仅涵盖输入(到程序)方面.
  • ?键盘输入的编码设置到控制台中.

  • 如果在整个会话期间将控制台切换为UTF-8 不是一个选项,则可以暂时为给定的呼叫执行此操作:

    # 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
    
    Run Code Online (Sandbox Code Playgroud)
  • 旧版Windows(早期版本W10)存在问题:

    • 在旧版本的Windows中65001,$OutputEncoding打破一些外部程序甚至批处理文件的控制台输出的活动值最终可能源于?Windows API函数中的错误(也被标准C库使用),它错误地报告了有效代码页面的字符数而不是字节€: 1,如本博文中所述.

    • 根据bobince对2008 年这个答案的评论,由此产生的症状是:"我的理解是,返回字节数的调用(例如fread/fwrite/etc)实际上返回了一些字符.这会导致各种各样的症状,例如输入读取不完整,fflush挂起,批处理文件损坏等等."

  • eryksun建议ConEmu作为原生Windows控制台窗口的优秀替代品.

    • 根据他的说法,这将解决"旧的GDI实现无法处理复杂脚本,非BMP字符或自动回退字体".


Jos*_*efZ 8

详细阐述了亚历山大·马丁的回答。出于测试目的,我创建了一些具有来自不同 Unicode 子范围的有效名称的文件夹和文件,如下所示:

有效名称

例如,使用Courier New控制台字体,在 PowerShell 控制台中显示替换符号而不是 CJK 字符:

快递新

另一方面,使用SimSun控制台字体时,会显示(不太明显)替换符号而不是阿拉伯语和希伯来语字符,而 CJK 字符似乎显示正确:

模拟太阳

请注意,仅显示所有替换符号,而保留真实字符,如您在以下PowerShell 控制台上方的复制和粘贴中所见:

PS D:\PShell> (Get-ChildItem 'D:\bat\UnASCII Names\' -Dir).Name
Arabic (?????????)
CJK (??(??))
Czech (?eština)
Greek (?????)
Hebrew (????????)
Japanese (???)
MathBoldScript ()
Russian (??????? ????)
Türkçe (Türkiye)
‹angles›
????
Run Code Online (Sandbox Code Playgroud)

为完整起见,以下是为 Windows 命令提示符启用更多字体的适当注册表值(这也适用于 Windows PowerShell 控制台):

(Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont' |
    Select-Object -Property [0-9]* | Out-String).Split( 
        [System.Environment]::NewLine, 
        [System.StringSplitOptions]::RemoveEmptyEntries) | 
     Sort-Object
Run Code Online (Sandbox Code Playgroud)

示例输出:

0       : Consolas
00      : Source Code Pro
000     : DejaVu Sans Mono
0000    : Courier New
00000   : Simplified Arabic Fixed
000000  : Unifont
0000000 : Lucida Console
932     : *?? ????
936     : *???
Run Code Online (Sandbox Code Playgroud)


Nea*_*rdt 8

如果您从 Microsoft Store(或预览版)安装 Microsoft 的“Windows 终端”,它会预先配置为完整的 Unicode 本地化。

\n

Windows 终端预览与雪人 \xe2\x9b\x84,阿拉伯语 (\xd8\xb9\xd9\x8e\xd8\xb1\xd9\x8e\xd8\xa8\xd9\x90\xd9\x8a\xd9\x91\xe2\x80 \x8e)、CJK (\xe4\xb8\xad\xe6\x96\x87(\xe7\xb9\x81\xe9\xab\x94))、捷克语 (\xc4\x8ce\xc5\xa1tina)、希腊语 (\xce) \x93\xcf\x81\xce\xb5\xce\xb5\xce\xba),希伯来语 (\xd7\xa2\xd6\xb4\xd7\x91\xd6\xb0\xd7\xa8\xd6\xb4\xd7\x99 \xd7\xaa)、日语 (\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e)、MathBoldScript ()、俄语 (\xd1\x80\xd1\x83\xd1\x81\xd1\x81 \xd0\xba\xd0\xb8\xd0\xb9 \xd1\x8f\xd0\xb7\xd1\x8b\xd0\xba), T\xc3\xbcrk\xc3\xa7e (T\xc3\xbcrkiye), \xe2\ x80\xb9angles\xe2\x80\xba,\xe2\x98\xba\xe2\x98\xbb\xe2\x99\xa5\xe2\x99\xa6

\n

您仍然无法输入带有特殊字符的命令...除非您使用 WSL!

\n

使用 WSL,我们可以运行 echo "snowman \xe2\x9b\x84"

\n


归档时间:

查看次数:

21434 次

最近记录:

5 年,11 月 前