将 PowerShell 的默认输出编码更改为 UTF-8

Changing PowerShell's default output encoding to UTF-8

提问人:rwallace 提问时间:10/18/2016 最后编辑:mklement0rwallace 更新时间:10/19/2023 访问量:280387

问:

默认情况下,将命令的输出重定向到文件或将其通过管道传递到 PowerShell 中的其他内容时,编码为 UTF-16,这没有用。我想把它改成UTF-8。

它可以根据具体情况通过替换语法来完成,但每次都必须重复这很尴尬。>foo.txt| out-file foo.txt -encoding utf8

在 PowerShell 中设置内容的持久方法是将它们放入 ;我已经验证了这个文件确实在启动时执行。\Users\me\Documents\WindowsPowerShell\profile.ps1

有人说可以设置输出编码,但我试过了,但没有效果。$PSDefaultParameterValues = @{'Out-File:Encoding' = 'utf8'}

https://blogs.msdn.microsoft.com/powershell/2006/12/11/outputencoding-to-the-rescue/ 乍一看似乎应该是相关的,但随后它谈到了以 ASCII 编码的输出,这并不是实际发生的事情。$OutputEncoding

如何将 PowerShell 设置为使用 UTF-8?

PowerShell UTF-8 字符编码

评论

1赞 js2010 11/7/2023
看起来 windows 11 默认为 utf8 [控制台]::outputencoding。

答:

249赞 mklement0 10/18/2016 #1

注意:

  • 下一节主要适用于 Windows PowerShell

  • 在这两种情况下,该信息都适用于使 PowerShell 使用 UTF-8 读取和写入文件

    • 相比之下,有关如何向外部程序发送和接收 UTF-8 编码字符串的信息,请参阅此答案
  • 现在(从最新版本的 Windows 10 开始)可以全系统切换到 UTF-8:请参阅此答案,但请注意以下注意事项:

    • 该功能具有深远的影响,因为 OEM 和 ANSI 代码页都设置为 ,即 UTF-8;此外,在撰写本文时,该功能仍被视为测试版功能(Windows 11 22H2)。65001
    • Windows PowerShell 中,这仅对默认为 ANSI 代码页的 cmdlet 生效,特别是 ,但不是 / ,并且它也适用于读取文件,特别是包括 PowerShell 本身读取源代码的方式。Set-ContentOut-File>Get-Content

Windows PowerShell 透视图:

  • PSv5.1 或更高版本中,其中 和 是 的有效别名,您可以通过 $PSDefaultParameterValues 首选项变量设置 > / >> / Out-File 的默认编码>>>Out-File

    • $PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'
    • 注意:
      • Windows PowerShell(其最新版本和最终版本为 v5.1)中,这总是会创建带有(伪)BOM 的 UTF-8 文件

        • 许多基于 Unix 的实用程序无法识别此 BOM(见底部);有关创建无 BOM 的 UTF-8 文件的解决方法,请参阅此文章
      • PowerShell (Core) v6+ 中,无 BOM 的 UTF-8 是默认的(请参阅下一节),但如果确实需要 BOM可以使用'utf8BOM'

  • PSv5.0 或更低版本中,您无法更改 > / >> 的编码,但在 PSv3 或更高版本上,上述技术确实适用于对 Out-File 的显式调用
    (首选项变量是在 PSv3.0 中引入的)。
    $PSDefaultParameterValues

  • PSv3.0 或更高版本中,如果要为支持
    -Encoding 参数
    (在 PSv5.1+ 中包括 和 )的所有 cmdlet 设置默认编码,请使用:
    >>>

    • $PSDefaultParameterValues['*:Encoding'] = 'utf8'

如果将此命令放在$PROFILE,则 Out-FileSet-Content 等 cmdlet 将默认使用 UTF-8 编码,但请注意,这使其成为会话全局设置,将影响所有未通过其参数显式指定编码的命令/脚本。-Encoding

同样,请确保在脚本模块中包含您希望以相同方式运行的命令,以便即使由其他用户或不同计算机运行,它们的行为也确实相同;但是,若要避免会话全局更改,请使用以下窗体创建 的本地副本:$PSDefaultParameterValues

  • $PSDefaultParameterValues = @{ '*:Encoding' = 'utf8' }

有关许多 Windows PowerShell 标准 cmdlet 中极不一致的默认字符编码行为的摘要,请参阅底部部分。


自动$OutputEncoding变量无关,仅适用于 PowerShell 与外部程序的通信方式(PowerShell 在向外部程序发送字符串时使用的编码) - 它与输出重定向运算符和 PowerShell cmdlet 用于保存到文件的编码无关。


可选阅读:跨平台视角:PowerShell Core

PowerShell 现在是跨平台的,通过其 PowerShell Core 版本,其编码 - 明智地 - 默认为无 BOM 的 UTF-8,与类 Unix 平台一致。

  • 这意味着没有 BOM 的源代码文件假定为 UTF-8,使用 / / 默认为无 BOM 的 UTF-8;显式使用该参数也会创建无 BOM 的 UTF-8,但您可以选择使用带有值的伪 BOM 创建文件。>Out-FileSet-Contentutf8-Encodingutf8bom

  • 如果在类 Unix 平台上使用编辑器创建 PowerShell 脚本,现在甚至在 Windows 上使用跨平台编辑器(如 Visual Studio Code 和 Sublime Text)创建 PowerShell 脚本,则生成的文件通常没有 UTF-8 伪 BOM:*.ps1

    • 这在 PowerShell Core 上工作正常。
    • 如果文件包含非 ASCII 字符,它可能会在 Windows PowerShell 上中断;如果确实需要在脚本中使用非 ASCII 字符,请使用 BOM 将其保存为 UTF-8。
      如果没有 BOM,Windows PowerShell(错误地)会将您的脚本解释为在旧版“ANSI”代码页中编码(由之前 Unicode 应用程序的系统区域设置确定;例如,美国英语系统上的 Windows-1252)。
  • 相反,具有 UTF-8 伪 BOM 的文件在类 Unix 平台上可能会出现问题,因为它们会导致 Unix 实用程序(如 、 和 )甚至某些编辑器(如 )传递伪 BOM,即将其视为数据catsedawkgedit

    • 这可能并不总是一个问题,但肯定是一个问题,例如当您尝试将文件读入字符串时,例如,或者 - 生成的变量将包含伪 BOM 作为前 3 个字节。bashtext=$(cat file)text=$(<file)

Windows PowerShell 中的默认编码行为不一致:

遗憾的是,Windows PowerShell 中使用的默认字符编码非常不一致;如上一节所述,跨平台 PowerShell Core 版本值得称赞地结束了这一点。

注意:

  • 以下内容并不希望涵盖所有标准 cmdlet。

  • 现在,通过谷歌搜索 cmdlet 名称以查找其帮助主题,默认情况下会显示这些主题的 PowerShell Core 版本;使用左侧主题列表上方的“版本”下拉列表切换到 Windows PowerShell 版本。

  • 从历史上看,文档经常错误地声称 ASCII 是 Windows PowerShell 中的默认编码;幸运的是,这已经得到了纠正。


写入以下内容的 Cmdlet:

Out-File和 / 创建“Unicode” - UTF-16LE - 默认情况下的文件 - 其中每个 ASCII 范围的字符 (too) 都由 2 个字节表示 - 这与 / 显着不同(见下一点); 并创建 UTF-16LE 文件。>>>Set-ContentAdd-ContentNew-ModuleManifestExport-CliXml

Set-Content(如果文件尚不存在/为空)使用 ANSI 编码 (由活动系统区域设置的 ANSI 旧代码页指定的编码,PowerShell 调用)。Add-ContentDefault

Export-Csv确实创建了 ASCII 文件,如上所述,但请参阅下面的注释。-Append

Export-PSSession默认情况下,使用 BOM 创建 UTF-8 文件。

New-Item -Type File -Value当前创建 BOM-less(!)UTF-8 格式。

帮助主题还声称 ASCII 编码是默认的 - 我没有亲自验证过这一说法。Send-MailMessage

Start-Transcript 总是使用 BOM 创建 UTF-8 文件,但请参阅下面的注释。-Append

追加到现有文件的 Re 命令:

>> / Out-File -Append不要尝试匹配文件现有内容的编码。 也就是说,它们盲目地应用其默认编码,除非另有指示,否则 不是 的选项(除非在 PSv5.1+ 中间接通过 ,如上所示)。 简而言之:您必须知道现有文件内容的编码,并使用相同的编码进行追加。-Encoding>>$PSDefaultParameterValues

Add-Content是值得称赞的例外:在没有显式参数的情况下,它会检测现有编码并自动将其应用于新内容。谢谢,js2010。请注意,在 Windows PowerShell 中,这意味着如果现有内容没有 BOM,则应用的是 ANSI 编码,而在 PowerShell Core 中则为 UTF-8。-Encoding

GitHub 问题 #9423 中讨论了 / 和 之间的这种不一致,这也会影响 PowerShell CoreOut-File -Append>>Add-Content

Export-Csv -Append 部分匹配现有编码:如果现有文件的编码是 ASCII/UTF-8/ANSI 中的任何一个,它会盲目地附加 UTF-8,但正确匹配 UTF-16LE 和 UTF-16BE
换句话说:在没有 BOM 的情况下,假设 UTF-8 是,而假设 ANSI。
Export-Csv -AppendAdd-Content

Start-Transcript -Append 部分匹配现有编码:它正确地将编码与 BOM 匹配,但在没有编码的情况下默认为可能有损的 ASCII 编码。


读取的 Cmdlet(即在没有 BOM 的情况下使用的编码):

Get-Content并默认为 ANSI (),这与 .
ANSI 也是 PowerShell 引擎本身在从文件中读取源代码时默认使用的 ANSI。
Import-PowerShellDataFileDefaultSet-Content

相反,在没有 BOM 的情况下,假定为 UTF-8,语及其参数也是如此。Import-CsvImport-CliXmlSelect-Stringswitch-File

评论

1赞 mvorisek 1/30/2019
有没有办法强制不在 Win10 上预置 BOM?
1赞 mklement0 1/30/2019
@Mvorisek:在 Windows PowerShell 中,您不能 - 您必须滚动自己的输出函数 - 请参阅 stackoverflow.com/a/34969243/45375。在 PowerShell Core(也在 Windows 上)中,无 BOM 是默认值。
2赞 mklement0 4/13/2019
@EliaWeiss,我不反对,但它是 Windows PowerShell,他们最终确实在 PowerShell Core 中做到了这一点。
2赞 mklement0 4/18/2019
@Marc:VS Code 和其他现代跨平台编辑器默认为 UTF-8,但这意味着它们会误解 ANSI 编码的文件。记事本使用启发式方法来猜测编码。关键是这只是一个猜测,因为任何 UTF-8 编码的文件也是技术上有效的 ANSI 编码文件(反之亦然)。如果 Windows 上的所有内容都像类 Unix 平台那样在没有 BOM 的情况下默认为 UTF-8,那就太好了,但事实并非如此,尤其是在 Windows PowerShell 中不是这样,尽管幸运的是现在在 PowerShell Core 中也是如此。
2赞 Sandburg 11/7/2019
要查看您的当前值(如果有的话),只需键入$PSDefaultParameterValues
4赞 pbies 5/24/2020 #2

简而言之,请使用:

write-output "your text" | out-file -append -encoding utf8 "filename"

您可能希望将脚本的某些部分放在大括号中,以便可以重定向一些命令的输出:

{
  command 1
  command 2
} | out-file -append -encoding utf8 "filename"

评论

1赞 mklement0 2/17/2021
引用这个问题:“可以根据具体情况通过替换语法来完成,但每次都必须重复这很尴尬。换句话说:您恰恰暗示了 OP 试图避免的内容。>foo.txt| out-file foo.txt -encoding utf8
1赞 Sasha Bond 3/3/2021
我认为应该删除-append
1赞 Phát Nguyễn Thành 10/3/2022 #3

在 Windows 上使用 PowerShell 和输出重定向进行的转储将创建具有 UTF-16 编码的文件。若要解决此问题,可以尝试:

mysqldump.exe [options] --result-file=dump.sql

参考链接: mysqldump_result-file