如何在Windows命令行中使用unicode字符?

How to use unicode characters in Windows command line?

我们在Team Foundation Server(TFS)中有一个非英语字符(?)在里面。当试图编写一些与构建相关的东西时,我们偶然发现了一个问题——我们不能通过?命令行工具的字母。命令提示符或其他什么东西会把它弄乱,tf.exe实用程序找不到指定的项目。

我尝试了不同格式的.bat文件(ansi,utf-8,有和没有bom)以及用javascript编写脚本(本质上是Unicode),但没有运气。如何执行一个程序并传递一个unicode命令行?


尝试:

1
chcp 65001

这会将代码页更改为UTF-8。此外,您还需要使用Lucida控制台字体。


我的背景:多年来,我在控制台中使用Unicode输入/输出(并且每天做很多工作)。此外,我还为这项任务开发了支持工具)。就您所了解的以下事实/限制而言,几乎没有问题:好的。

  • CMD和"console"是不相关的因素。CMD.exe只是准备在控制台("控制台应用程序")内"工作"的程序之一。
  • afaik,CMD完全支持Unicode;当任何代码页处于活动状态时,您可以输入/输出所有Unicode字符。
  • Windows控制台对Unicode有很多支持?-?但它并不完美(只是"足够好";见下文)。
  • chcp 65001非常危险。除非某个程序是专门为解决Windows的API中的缺陷而设计的(或者使用具有这些解决方法的C运行时库),否则它将无法可靠地工作。Win8修复?这些问题中,cp65001的问题,但其余的问题仍然适用于win10。
  • 我在江户十一〔五〕工作。正如我已经说过的:要在控制台中输入/输出Unicode,不需要设置代码页。

细节

  • 要将Unicode读/写到控制台,应用程序(或其C运行时库)应该足够智能,不使用File-I/OAPI,而是使用Console-I/OAPI。(例如,请参阅python是如何做到的。)
  • 同样,要读取Unicode命令行参数,应用程序(或其C运行时库)应该足够智能,可以使用相应的API。
  • 控制台字体呈现仅支持BMP中的Unicode字符(换句话说:在U+10000下面)。只支持简单的文本呈现(那么欧洲?-?还有一些东亚人?-?语言应该很好用?-?就使用预组合形式而言)。[这里有一个小的印刷体,用于东亚和字符U+0000、U+0001、U+30FB。]

实际考虑

  • 窗口上的默认值不是很有用。为了获得最佳体验,应该调整3个配置:好的。

    • 输出:一个综合的控制台字体。为了获得最佳效果,我推荐我的构建。(安装说明在那里?-?并在本页的其他答案中列出。)
    • 输入:一个功能强大的键盘布局。为了获得最佳效果,我推荐我的布局。
    • 对于输入:允许Unicode的十六进制输入。
  • 还有一个"粘贴"到控制台应用程序中的gotcha(非常技术性):好的。

    • 十六进制输入在AltKeyUp上传递一个字符;所有其它传递字符的方法都发生在KeyDown上;因此许多应用程序还没有准备好在KeyUp上看到一个字符。(仅适用于使用Console-I/OAPI的应用。)
    • 结论:许多应用程序不会对十六进制输入事件做出反应。
    • 此外,"粘贴"字符会发生什么情况取决于当前键盘布局:如果可以在不使用前缀键的情况下键入字符(但使用任意复杂的修饰符组合,如Ctrl-Alt-AltGr-Kana-Shift-Gray*中所述),则该字符将在模拟按键上交付。这是任何应用程序所期望的?-?所以粘贴任何只包含这些字符的东西都可以。
    • 但是,通过模拟十六进制输入来传递"其他"字符。

    结论:除非您的键盘布局支持不带前缀键的大量字符输入,否则当您通过控制台的ui:Alt-Space E P使用Paste时,某些错误的应用程序可能会跳过字符。(这就是我推荐使用键盘布局的原因!)好的。

还应该记住,用于Windows的"可选的、功能更强的"控制台根本不是控制台。它们不支持Console-I/OAPI,因此依赖这些API工作的程序将无法工作。(不过,仅使用"控制台文件句柄的文件I/O API"的程序可以正常工作。)好的。

这种非控制台的一个例子是微软的Powershell的一部分。我不使用它;先试验,再按和释放WinKey,然后输入Powershell。好的。

(另一方面,有些程序,如ConEmuANSICON试图做得更多:它们"试图"拦截Console-I/OAPI,使"真正的控制台应用程序"也能工作。这绝对适用于玩具示例程序;在现实生活中,这可能解决或不解决您的特定问题。实验。)好的。总结

  • 设置字体、键盘布局(可选,允许十六进制输入)。好的。

  • 只使用通过Console-I/OAPI的程序,并接受unicode命令行参数。例如,任何cygwin编译的程序都可以。正如我已经说过的,江户十一〔十七〕也很好。好的。

upd:最初,对于cp65001中的一个bug,我混合了内核层和crtl层(upd2:和Windows用户模式API!)另外:Win8修复了一半的bug;我澄清了关于"更好的控制台"应用程序的部分,并添加了一个关于python如何做的参考。好的。好啊。


我也有同样的问题(我来自捷克共和国)。我有一个英文版的Windows安装程序,我必须在共享驱动器上处理文件。文件路径包括捷克语特定字符。

适合我的解决方案是:

在批处理文件中,更改Charset页

我的批处理文件:

1
2
chcp 1250
copy"O:\VE?EJNé\??????\?.xls" c:\temp

批处理文件必须保存在CP1250中。

注意控制台不会正确显示字符,但它会理解它们…


检查非Unicode程序的语言。如果在Windows控制台中有俄语问题,则应在此处设置俄语:

Changing language for non-Unicode programs


更改Windows控制台的默认代码页非常困难。当你在网上搜索时,你会发现不同的建议,但是其中一些建议可能会完全破坏你的窗口,也就是说,你的电脑不再启动。

最安全的解决方案是:转到注册表项HKEY_CURRENT_USER\Software\Microsoft\Command Processor并添加字符串值Autorun=chcp 65001

或者,您可以将这个小批量脚本用于最常见的代码页。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
@ECHO off

SET ROOT_KEY="HKEY_CURRENT_USER"


FOR /f"skip=2 tokens=3" %%i in ('reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
ls\CodePage /v OEMCP') do set OEMCP=%%i

ECHO System default values:

ECHO.
ECHO ...............................................
ECHO Select Codepage
ECHO ...............................................
ECHO.
ECHO 1 - CP1252
ECHO 2 - UTF-8
ECHO 3 - CP850
ECHO 4 - ISO-8859-1
ECHO 5 - ISO-8859-15
ECHO 6 - US-ASCII
ECHO.
ECHO 9 - Reset to System Default (CP%OEMCP%)
ECHO 0 - EXIT
ECHO.


SET /P  CP="Select a Codepage:"

if %CP%==1 (
    echo Set default Codepage to CP1252
    reg add"%ROOT_KEY%\Software\Microsoft\Command Processor" /v Autorun /t REG_SZ /d"@chcp 1252>nul" /f
) else if %CP%==2 (
    echo Set default Codepage to UTF-8
    reg add"%ROOT_KEY%\Software\Microsoft\Command Processor" /v Autorun /t REG_SZ /d"@chcp 65001>nul" /f
) else if %CP%==3 (
    echo Set default Codepage to CP850
    reg add"%ROOT_KEY%\Software\Microsoft\Command Processor" /v Autorun /t REG_SZ /d"@chcp 850>nul" /f
) else if %CP%==4 (
    echo Set default Codepage to ISO-8859-1
    add"%ROOT_KEY%\Software\Microsoft\Command Processor" /v Autorun /t REG_SZ /d"@chcp 28591>nul" /f
) else if %CP%==5 (
    echo Set default Codepage to ISO-8859-15
    add"%ROOT_KEY%\Software\Microsoft\Command Processor" /v Autorun /t REG_SZ /d"@chcp 28605>nul" /f
) else if %CP%==6 (
    echo Set default Codepage to ASCII
    add"%ROOT_KEY%\Software\Microsoft\Command Processor" /v Autorun /t REG_SZ /d"@chcp 20127>nul" /f
) else if %CP%==9 (
    echo Reset Codepage to System Default
    reg delete"%ROOT_KEY%\Software\Microsoft\Command Processor" /v AutoRun /f
) else if %CP%==0 (
    echo Bye
) else (
    echo Invalid choice
    pause
)

使用@chcp 65001>nul而不是chcp 65001,每次启动新的命令行窗口时都会抑制输出"active code page:65001"。

从代码页标识符中可以获得的所有可用数字的完整列表

注意,这些设置仅适用于当前用户。如果您想为所有用户设置,请用SET ROOT_KEY="HKEY_LOCAL_MACHINE"替换行SET ROOT_KEY="HKEY_CURRENT_USER"


实际上,诀窍是命令提示符实际上理解这些非英语字符,只是无法正确显示它们。

当我在命令提示符中输入包含一些非英语字符的路径时,它显示为"??????????????????"。当您提交命令(CD)时????????????????????"在我的情况下),一切都按预期工作。


在Windows 10 x64计算机上,我通过以下方式使命令提示符显示非英语字符:

打开提升的命令提示符(以管理员身份运行cmd.exe)。通过以下方式向注册表查询控制台的可用TrueType字体:

1
    REG query"HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont"

您将看到如下输出:

1
2
3
4
    0    REG_SZ    Lucida Console
    00    REG_SZ    Consolas
    936    REG_SZ    *新宋体
    932    REG_SZ    *MS ゴシック

现在我们需要添加一个TrueType字体来支持您需要的字符,比如Courier New。我们通过在字符串名称中添加零来实现这一点,因此在本例中,下一个将是"000":

1
    REG ADD"HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont" /v 000 /t REG_SZ /d"Courier New"

现在我们实现了UTF-8支持:

1
    REG ADD HKCU\Console /v CodePage /t REG_DWORD /d 65001 /f

将默认字体设置为"Courier New":

1
    REG ADD HKCU\Console /v FaceName /t REG_SZ /d"Courier New" /f

将字体大小设置为20:

1
    REG ADD HKCU\Console /v FontSize /t REG_DWORD /d 20 /f

如果需要,启用快速编辑:

1
    REG ADD HKCU\Console /v QuickEdit /t REG_DWORD /d 1 /f


由于我没有看到任何关于Python2.7的完整答案,所以我将概述两个重要步骤和一个非常有用的可选步骤。

  • 您需要支持Unicode的字体。Windows附带Lucida控制台,可以通过右键单击命令提示符的标题栏并单击Defaults选项来选择。这也可以使用颜色。请注意,您也可以通过选择Properties来更改以特定方式调用的命令窗口的设置(例如,在此处打开,Visual Studio)。
  • 您需要将代码页设置为cp65001,这似乎是微软试图为命令提示提供utf-7和utf-8支持。通过在命令提示符中运行chcp 65001来实现这一点。一旦设置好,它将保持这种方式,直到窗口关闭。每次启动cmd.exe时都需要重新执行此操作。
  • 要获得更持久的解决方案,请参阅超级用户上的这个答案。简而言之,在HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor上使用regedit创建一个REG_SZ字符串条目,并将其命名为AutoRun。将其值更改为chcp 65001。如果不想看到命令的输出消息,请使用@chcp 65001>nul

    有些程序在与这种编码进行交互时遇到了问题,mingw是一个值得注意的程序,它在编译时失败,并带有一条无意义的错误消息。尽管如此,这仍然非常有效,并且不会导致大多数程序出现错误。


    一个非常简单的选项是安装一个Windows bash shell,如mingw,并使用它:

    Enter image description here

    有一点学习曲线,因为您需要使用Unix命令行功能,但是您会喜欢它的强大功能,您可以将控制台字符集设置为utf-8。

    Enter image description here

    当然,你也会得到像grep、find、less等所有常见的*nix商品。


    对于类似的问题(我的问题是在命令提示下显示MySQL中的utf-8字符)。

    我是这样解决的:

  • 我将命令提示符的字体改为lucida console。(此步骤必须与您的情况无关。它只与你在屏幕上看到的内容有关,而与真正的角色无关)。

  • 我把代码页改成了Windows-1253。您可以在"chcp 1253"命令提示下执行此操作。在我想看UTF-8的地方,它对我的情况很有用。


  • 这个问题很烦人。我的文件名和文件内容中通常有汉字。请注意,我使用的是Windows 10,下面是我的解决方案:

    如果在Windows10上安装了UbuntuBash,则显示文件名,如dirls

  • 将区域设置为支持非UTF 8字符。

  • 之后,控制台的字体将更改为该区域设置的字体,并且还会更改控制台的编码。

  • 在完成前面的步骤之后,为了使用命令行工具显示utf-8文件的文件内容

  • chcp 65001将页面改为utf-8
  • 更改为支持UTF-8的字体,如Lucida控制台
  • 使用type命令查看文件内容,如果在Windows10上安装了ubuntu bash,则使用cat命令查看文件内容。
  • 请注意,在将控制台的编码设置为utf-8之后,我不能使用中文输入法在cmd中键入汉字。
  • 最懒惰的解决方案:只需使用控制台模拟器,如http://cmder.net/


    更干净的方法是:安装可用的免费Microsoft日语语言包。(其他的东方语言包也可以,但我已经测试过日本语言包。)

    这将为您提供具有较大字形集的字体,使它们成为默认行为,更改各种Windows工具,如cmd、wordpad等。


    如果在DOS窗口中键入路径/文件名时,计算机显示路径/文件名正确,则快速决定.bat文件:

  • 复制con temp.txt[按Enter键]
  • 键入路径/文件名[按Enter键]
  • 按Ctrl-Z[按Enter键]
  • 这样就可以创建一个.txt文件-temp.txt。在记事本中打开它,复制文本(不要担心它看起来不可读),然后粘贴到.bat文件中。在DOS窗口中执行以这种方式创建的.bat对m快速(西里尔文,保加利亚语)有效。


    我发现这种方法在新版本的Windows10中非常有用:

    启用此功能:"beta:使用Unicode UTF-8提供全球语言支持"

    Control panel -> Regional settings -> Administrative tab-> Change
    system locale...

    Region Settings


    我在这里看到了几个答案,但它们似乎没有解决这个问题——用户希望从命令行获得unicode输入。

    Windows使用UTF-16编码两个字节的字符串,因此您需要从程序中的操作系统中获取这些字符串。有两种方法可以做到这一点-

    1)Microsoft有一个扩展,允许main采用宽字符数组:int wmain(int argc,wchar_t*argv[]);https://msdn.microsoft.com/en-us/library/6wd819wh.aspx

    2)调用Windows API获取命令行的Unicode版本wchar_t win_argv=(wchar_t)commandlinetoargvw(getcommandlinen(),&nargs);https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-commandlinetoargvw

    阅读:http://utf8everywhere.org有关详细信息,尤其是在支持其他操作系统的情况下。


    将代码页更改为1252对我来说是有效的。对我来说,问题是符号double doller正在由DOS在WindowsServer2008上转换为另一个符号。

    我在我的BCP声明^§中使用了CHCP 1252和它前面的一个CAP。


    我在删除unicode命名文件时遇到了一个类似的问题,通过在批处理文件中用它们的短(8点3)名引用它们。

    通过执行dir /x可以查看短名称。显然,这只适用于已知的Unicode文件名。


    到UTF-8:chcp 65001

    返回默认值:chcp 437