求教, bat 脚本里,设了 chcp 仍然有中文无法正确显示 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
sugarsalt
V2EX    程序员

求教, bat 脚本里,设了 chcp 仍然有中文无法正确显示

  •  
  •   sugarsalt 2023-09-21 15:17:29 +08:00 1426 次点击
    这是一个创建于 749 天前的主题,其中的信息可能已经有所发展或是发生改变。
    从 stackoverflow 抄了一段用来使得特定行输出不一样颜色的 bat 脚本,但是用来输出中文文本会乱码
    用了 chcp 65001 也不行
    我的实验脚本如下
    @echo off
    SETLOCAL EnableDelayedExpansion
    chcp 65001 >nul

    for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
    set "DEL=%%a"
    )

    set "text=什么"
    echo %text%
    call :ColorText 0c "%text%"
    call :ColorText 0c "shen me"

    pause

    :ColorText
    echo off
    echo %DEL% > "%~2"
    findstr /v /a:%1 /R "^$" "%~2" nul
    del "%~2" > nul 2>&1
    goto :eof

    echo 能正常显示“什么”,call :ColorText 0c "%text%"就不行

    颜色代码来自前两个最高分回答
    https://stackoverflow.com/questions/21660249/how-do-i-make-one-particular-line-of-a-batch-file-a-different-color-then-the-oth

    我看不懂原本那个改颜色代码的原理,所以想请问一下大家有没有解决的办法?
    谢谢
    6 条回复    2023-09-22 04:51:17 +08:00
    geelaw
        1
    geelaw  
       2023-09-21 16:38:15 +08:00   2
    这段代码相当糟糕,是利用 findstr 这个工具显示文件名,因此你传入的字符串必须是合法的文件名,而且显示的时候会覆盖当前目录下的同名文件总之就是个不定时炸弹。

    如果必须要用 batch ,推荐 https://gist.github.com/mlocati/fdabcaeb8071d5c75a2d51712db24011
    否则可以考虑 PowerShell

    另外请不要在 bat 里面 chcp ,这是在劫持用户的 console ,而且我没找到如何让 Windows 以固定的编码读取 batch 的功能,它或许永远是以系统代码页读取 batch 并运行的,也可能是按照当前代码页一次读取一行运行的。考虑如下 UTF-8 的 batch:

    chcp 932>nul 2>nul
    chcp 65001>nul 2>nul && echo

    其中 echo 的字符是 U+00BF ,它的 UTF-8 编码是 0xC2 0xBF ,一开始的 932 是 Windows 的 Shift JIS 实现,在这个代码页里 0xC2 不是合法的开头字节,因此在默认的日语 Windows 上执行它会产生不可预知的后果。

    实际效果是打印出来的并不是倒转的问号,而是 这两个符号。
    geelaw
        2
    geelaw  
       2023-09-21 17:17:00 +08:00
    至于原来的代码为什么不行,假设 batch 是 UTF-8 保存的,且本机代码页是 936 ,那么最终有颜色的输出结果是 "",这是把 "什么" 用 Windows-936 (~ GB) 编码之后再用 UTF-8 解码,这说明 cmd 设置变量的时候,是用 UTF-8 解读 batch 文件的(从而正确把文件中的字节解读为 "什么"),但是数据传入 findstr.exe 之后变成了 Windows-936 ,这很可能是因为 findstr.exe 使用的不是 WCHAR 而是 CHAR (因此 argv 是根据系统代码页,也就是 936 ,解读的,因此 findstr.exe 内部看到的是 GB 编码的 "什么"),并且在最后 findstr.exe 向控制台以输出了它所得到的字节流(即输出了 GB 编码的 "什么")但控制台的代码页是 UTF-8 ,因此它把 GB 编码的 "什么" 用 UTF-8 解读并显示。
    adoal
        3
    adoal  
       2023-09-21 17:21:19 +08:00
    还是不要尝试在 code page 时代的遗产软件上用 Unicode 了。天生的缺陷。
    ysc3839
        4
    ysc3839  
       2023-09-21 18:02:57 +08:00 via Android
    @geelaw 那个 gist 的代码其实还能简化,可以直接 set ESC=然后后面复制一个 ESC 字符进去,不需要 for 啥的。
    具体参见 https://github.com/Maximus5/ConEmu/blob/master/Release/ConEmu/SetEscChar.cmd
    xiangyuecn
        5
    xiangyuecn  
       2023-09-21 19:50:42 +08:00
    太骚了,用 findstr 来显示不同颜色的文件名,输出些简单的标签文本还行,Log 、Warn 、Error

    要通用,还是直接 bat 所在目录放一个可以输出不同颜色文本的 exe ( cmdcolor.exe 之类的),echo 换成这个 exe 就搞定了( findstr 命令本身就是 findstr.exe )
    sugarsalt
        6
    sugarsalt  
    OP
       2023-09-22 04:51:17 +08:00
    @geelaw #1 感谢解答!
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5238 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 05:51 PVG 13:51 LAX 22:51 JFK 01:51
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86