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

默认情况下,当您将命令的输出重定向到一个文件或将其导入 PowerShell 的其他文件时,编码是 UTF-16,这是没有用的。我想把它改成 UTF-8。

通过用 | out-file foo.txt -encoding utf8替换 >foo.txt语法,可以逐个地完成这项工作,但是每次都必须重复这项工作是很麻烦的。

在 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/ 谈论的是 $OutputEncoding,乍一看似乎它应该是相关的,但接下来它谈论的是用 ASCII 编码的输出,这并不是实际发生的情况。

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

232653 次浏览

注:

  • 下一个部分主要适用于 Windows PowerShell

    • 请参阅 环境影响评估小组它的跨平台 一个 href = “ https://github.com/PowerShell/PowerShell/blob/master/README.md”rel = “ noReferrer”> PowerShell < em > Core (v6 +) 版本。
  • 在这两种情况下,信息适用于使 PowerShell 使用 UTF-8读写 < em > files

    • 相比之下,对于 关于如何向 < em > 外部程序发送和接收 UTF-8编码的 < em > 字符串 的信息,请参阅 这个答案

  • PSv5.1或更高版本中,>>>实际上是 Out-File的别名,你可以选择 通过 ABC6首选项变量设置 ABC0/ABC1/Out-File的默认编码:

    • $PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'
    • 注:
      • Windows PowerShell(其最新和最终版本是 v5.1的遗留版本)中,这个 总是用 < a href = “ https://en.wikipedia.org/wiki/Byte _ order _ mark # UTF-8”rel = “ noReferrer”> (伪) BOM 创建 UTF-8文件

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

  • PSv5.0或以下版本,你 < em > 不能 更改 ABC0/>>的编码,但是,在 PSv3或更高版本,上面的技术 对于显式调用 Out-File,< em > 是否起作用
    (在 PSv3.0中引入了 $PSDefaultParameterValues偏好变量)。

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

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

如果您将这个命令放在 $PROFILE 中,那么这样的 cmdlet 在默认情况下将使用 UTF-8编码,但是请注意,这将使它成为一个 会话-全局设置,它将影响所有没有通过其 -Encoding参数显式指定编码的命令/脚本。

类似地,使用 确保在您的 < em > script 或 < em > module 中包含您希望以同样方式执行的命令,即使在另一个用户或不同的计算机运行时,它们的行为也是相同的; 然而,为了避免会话 全球性的的更改,使用以下表单来创建 $PSDefaultParameterValues本地副本:

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

有关 很多字符编码标准 cmdlet 的默认 Windows PowerShell 行为非常不一致,请参见底部部分。


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


可选阅读: 跨平台视角: PowerShell 核心:

PowerShell 现在通过其 PowerShell < em > Core 版本跨平台 ,其编码合理的 默认值为 < em > BOM-less UTF-8 与类 Unix 平台一致。

  • 这意味着没有 BOM 的源代码文件被假定为 UTF-8,并且使用 >/Out-File/Set-Content默认为 BOM-less UTF-8; 显式使用 utf8 -Encoding参数也会创建 BOM-less UTF-8,但是您可以选择创建带有 utf8bom值的伪 BOM 文件

  • 如果你在一个类 Unix 平台上用编辑器创建 PowerShell 脚本,现在甚至在 窗户上用跨平台编辑器如 Visual Studio Code 和 Sublime Text 创建 PowerShell 脚本,得到的 *.ps1文件通常会有一个 UTF-8伪 BOM:

    • 这在 PowerShell 核心上可以很好地工作。
    • 如果文件包含非 ASCII 字符,它可能在 Windows PowerShell上中断; 如果您确实需要在脚本中使用非 ASCII 字符,则将它们保存为 UTF-8与 BOM 合作
      如果没有物料清单,Windows PowerShell 会将你的脚本解释为编码在遗留的“ ANSI”代码页中(由 Unicode 之前的应用程序的系统区域设置决定,例如,美英系统上的 Windows-1252)。
  • 相反,在类 Unix 平台上,使用 UTF-8伪 BOM 的 文件可能会出现问题,因为它们会导致 Unix 实用程序(如 catsedawk)甚至一些编辑器(如 gedit)将 通过伪 BOM变成 资料

    • 这可能不是 一直都是的问题,但肯定会有问题,比如当你试图用 text=$(cat file)text=$(<file)将一个文件读入一个字符串 bash时,结果变量将包含前3个字节的伪 BOM。

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

遗憾的是,字符编码中使用的默认 Windows PowerShell 非常不一致,正如前一节所讨论的,跨平台的 PowerShell 核心版本已经很好地解决了这个问题。

注:

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

  • 现在,通过搜索 cmdlet 名称来查找它们的帮助主题,默认情况下将显示主题的 PowerShell 核心版本; 使用左侧主题列表上方的版本下拉列表切换到 Windows PowerShell版本。

  • 在撰写本文时,文档经常错误地声称 ASCII 是 Windows PowerShell 中的默认编码——参见 这个 GitHub 文档的问题


Cmdlets that 写作:

Out-File>/>>创建“ Unicode”-UTF-16LE-文件默认情况下-其中每个 ASCII-range 字符(也)由 2字节表示-这明显不同于 Set-Content/Add-Content(见下一点) ; New-ModuleManifestExport-CliXml也创建 UTF-16LE 文件。

Set-Content(如果文件不存在/为空,则为 Add-Content)使用 ANSI 编码(由活动系统区域设置的 ANSI 遗留代码页指定的编码,PowerShell 称之为 Default)。

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

Export-PSSession默认使用 BOM 创建 UTF-8文件。

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

Send-MailMessage帮助主题还声明 ASCII 编码是默认的——我还没有亲自验证这个声明。

Start-Transcript 一成不变创建 UTF-8文件 BOM,但请参阅下面的注释 re-Append

重新命令 附录到现有文件:

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

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

GitHub 的问题中讨论了 Out-File -Append/>>Add-Content之间的这种不一致性,这种不一致性也会影响 PowerShell 核心

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

Start-Transcript -Append 一部分匹配现有的编码: 它正确匹配编码 与 BOM 合作,但缺省情况下可能有损失的 ASCII 编码。


使用 (即 没有物料清单中使用的编码)的 Cmdlet:

Get-ContentImport-PowerShellDataFile默认为 ANSI (Default) ,这与 Set-Content一致。
当 PowerShell 引擎从文件中读取 源代码时,ANSI 也是 PowerShell 引擎本身的默认值。

相比之下,Import-CsvImport-CliXmlSelect-String在没有 BOM 的情况下假设 UTF-8。

简而言之,使用:

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

您可能需要将脚本的某些部分放入大括号中,以便重定向几个命令的输出:

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

在 Windows 上使用 PowerShell 和输出重定向生成的转储将创建一个具有 UTF-16编码的文件。为了解决这个问题,你可以试试:

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

参考链接: Mysqldump _ result-file