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

问题描述 投票:51回答:1

默认情况下,当您将命令的输出重定向到文件或将其传递到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?

powershell utf-8 character-encoding
1个回答
79
投票

注意:以下内容适用于Windows PowerShell。有关跨平台PowerShell核心版本的信息,请参阅下一节。

  • 在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中,则Out-FileSet-Content等cmdlet默认情况下将使用UTF-8编码,但请注意,这使其成为会话全局设置,将影响未明确指定编码的所有命令/脚本。

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

警告:PowerShell,从v5.1开始,总是使用(pseudo) BOM创建UTF-8文件,这在Windows世界中是惯用的 - 基于Unix的实用程序无法识别此BOM(参见底部)。

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


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


Optional reading: The cross-platform perspective: PowerShell Core:

PowerShell is now cross-platform,通过其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脚本,现在甚至在具有跨平台编辑器(如Visual Studio Code和Sublime Text)的Windows上创建PowerShell脚本,生成的*.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平台上可能会出现问题,因为它们会导致诸如catsedawk等Unix实用程序 - 甚至某些编辑器(如gedit)传递伪BOM通过,即将其视为数据。 这可能并不总是一个问题,但绝对可以,例如当您尝试将文件读入bash中的字符串时,例如text=$(cat file)text=$(<file) - 结果变量将包含伪BOM作为前3个字节。

Inconsistent default encoding behavior in Windows PowerShell:

遗憾的是,Windows PowerShell中使用的默认字符编码非常不一致;正如前一节所讨论的,跨平台的PowerShell核心版本已经值得称道地说明了这一点。

注意:

  • 以下并不希望涵盖所有标准cmdlet。
  • 现在,Google搜索cmdlet名称以查找其帮助主题,默认情况下会显示主题的PowerShell核心版本;使用左侧主题列表上方的版本下拉列表切换到Windows PowerShell版本。
  • 在撰写本文时,文档经常错误地声称ASCII是Windows PowerShell中的默认编码 - 请参阅this GitHub docs issue

编写的Cmdlet:

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

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

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

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

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

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

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

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

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

Out-File -Append中讨论了>> / Add-Contentthis GitHub issue之间的这种不一致,这也影响了PowerShell Core。

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


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

Get-ContentImport-PowerShellDataFile默认为ANSI(Default),这与Set-Content一致。

相比之下,Import-CsvImport-CliXmlSelect-String假设没有BOM的UTF-8 - 不像Get-ContentImport-PowerShellDataFile

© www.soinside.com 2019 - 2024. All rights reserved.