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


105

默认情况下,当您将命令的输出重定向到文件或将其通过管道传递到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/讨论$OutputEncoding乍一看似乎应该是相关的,但随后讨论的是编码输出以ASCII表示,这实际上不是实际情况。

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

Answers:


162

注意:以下内容适用于Windows PowerShell
请参阅下一节以了解跨平台的PowerShell Core(v6 +)版本。

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

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

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

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

如果你在把这个命令$PROFILE一样,cmdlet这样Out-FileSet-Content将默认使用UTF-8编码,但请注意,这使得它的会话全局设置,将影响所有命令/脚本,没有明确指定编码。

同样,请确保在脚本或模块中包含要以相同方式运行的此类命令,以便即使在由其他用户或其他计算机运行时,它们的运行方式也确实相同。

警告:**从v5.1开始,PowerShell始终使用(伪)BOM _ **创建UTF-8文件_,这仅在Windows世界中很常见-基于Unix的实用程序无法识别该BOM(请参阅底部);有关创建无BOM的UTF-8文件的变通办法,请参阅此文章

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


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


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

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

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

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

    • 在PowerShell Core上运行良好。
    • 如果文件包含非ASCII字符,则在Windows PowerShell上可能会中断;如果确实需要在脚本中使用非ASCII字符,请使用BOM将它们另存为UTF-8 。
      如果没有BOM,Windows PowerShell(mis)会将您的脚本解释为在旧版“ ANSI”代码页中编码(由Unicode之前的应用程序的系统语言环境确定;例如,在美式英语系统中为Windows-1252)。
  • 相反,文件有UTF-8的伪BOM是有问题的,在UNIX平台上,因为它们会导致Unix工具,例如catsedawk-甚至一些编辑器,例如gedit-到通过传递伪BOM,即把它当作数据

    • 这可能并不总是一个问题,但绝对可以,例如,当您尝试将文件读入bash带有text=$(cat file)text=$(<file)-的字符串时,结果变量将包含伪BOM作为前3个字节。

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

遗憾的是,Windows PowerShell中使用的默认字符编码完全不一致。上一节中讨论的跨平台PowerShell Core版本值得称赞并结束了这一点。

注意:

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

  • 在默认情况下,使用谷歌搜索cmdlet名称查找其帮助主题将向您显示主题的PowerShell Core版本;使用左侧主题列表上方的版本下拉列表切换到Windows PowerShell版本。

  • 在撰写本文时,文档经常错误地声称ASCII是Windows PowerShell中的默认编码-请参阅此GitHub docs issue


编写的Cmdlet :

Out-File>/>>创建默认情况下的“ Unicode”文件-UTF-16LE-其中每个ASCII范围字符(太)都由2个字节表示-与Set-Content/明显不同Add-Content(请参阅下一点);New-ModuleManifestExport-CliXml创建UTF-16LE文件。

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

Export-Csv确实会创建ASCII文件,如记录所示,但请参阅-Append下面的注释。

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

New-Item -Type File -Value 当前创建无BOM的(!)UTF-8。

Send-MailMessage帮助主题还声称,ASCII编码是默认的-我没有亲自验证要求。

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

重新添加到现有文件的命令:

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

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

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

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

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


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

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

相比之下,Import-CsvImport-CliXmlSelect-String假定在不存在BOM的UTF-8。


您能解释一下5.1如何>/>>成为有效的别名Out-File吗?
马克西米利安·伯兹利

@ TheIncorrigible1:可能是PetSerAl向我指出了这一点,但我不记得在哪里以及如何去做。Windows PowerShell是封闭源代码,但是由于相同的准别名关系也适用于PowerShell Core,因此您应该能够在后者的源代码中找到它。
mklement0 '18

2
我不同意@EliaWeiss,但它专门用于Windows PowerShell,最终他们确实在PowerShell Core中做到了。
mklement0

2
@Marc:值得称赞的是VS Code和其他现代跨平台编辑器默认使用UTF-8,但这意味着它们会误解ANSI编码的文件。记事本使用试探法猜测编码。关键是,这只是一个猜测,因为任何UTF-8编码的文件也是技术上有效的ANSI编码的文件(但反之则不是)。如果没有像Unix平台那样的BOM,Windows上的所有内容都默认为UTF-8,那就太好了,但是事实并非如此,尤其是在Windows PowerShell中,尽管幸运的是,现在在PowerShell Core中就是这种情况。
mklement0

2
要查看当前值(如果有的话),只需键入$PSDefaultParameterValues
Sandburg

3

简而言之,请使用:

write-output "your text" | out-file -append -encoding utf8 "filename"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.