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

时间:2016-10-18 02:54:15

标签: powershell utf-8 character-encoding

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

2 个答案:

答案 0 :(得分:75)

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

  • 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用于保存到文件的编码无关。

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

PowerShell is now cross-platform,通过其 PowerShell Core 版本,其编码 - 明智地 - 默认为无BOM的UTF-8 ,符合类Unix平台。

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

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

    • 这适用于PowerShell Core
    • 如果文件包含非ASCII字符,它可能会在 Windows PowerShell 上中断;如果您确实需要在脚本中使用非ASCII字符,请将它们保存为带有BOM 的UTF-8
      如果没有BOM,Windows PowerShell(mis)会将您的脚本解释为在旧版" ANSI"代码页(由Unicode前应用程序的系统区域设置决定;例如,美英系统上的Windows-1252)。
  • 相反,的文件具有UTF-8伪BOM可能会在类Unix平台上出现问题,因为它们会导致诸如*.ps1,{{{ 1}}和cat - 甚至某些编辑器,例如sed - 通过传递伪BOM,即将其视为数据

    • 这可能不会始终成为问题,但绝对可以,例如当您尝试将文件读入awk中的字符串时,例如geditbash - 结果变量将伪BOM作为前3个字节。

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

令人遗憾的是,Windows PowerShell中使用的默认字符编码非常不一致;正如前一节所讨论的,跨平台的PowerShell Core 版本已经值得称道地为此付出了代价。

注意:

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

  • Google搜索cmdlet名称以查找其帮助主题现在默认显示主题的PowerShell Core 版本;使用左侧主题列表上方的版本下拉列表切换到 Windows PowerShell 版本。

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

的Cmdlet:

text=$(cat file)text=$(<file) / Out-File创建&#34; Unicode&#34; - UTF-16LE - 默认情况下的文件 - 其中每个ASCII范围字符(也)由 2 字节表示 - 这与> / >>明显不同(见下一点); Set-ContentAdd-Content也会创建UTF-16LE文件。

New-ModuleManifest(如果文件尚未存在,则为Export-CliXml /为空)使用ANSI编码(由活动系统区域设置和ANSI遗留代码页指定的编码, PowerShell调用Set-Content)。

Add-Content确实创建了ASCII文件,如文档所述,但请参阅下面的注释Default

Export-Csv默认情况下会创建带有BOM的UTF-8文件。

-Append目前创建无BOM(!)UTF-8。

Export-PSSession帮助主题还声称ASCII编码是默认设置 - 我尚未亲自验证该声明。

追加的命令发送到现有文件:

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

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

this GitHub issue中讨论Add-Content / -EncodingOut-File -Append之间的不一致,这也会影响PowerShell Core

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

读取 的Cmdlet(在缺少BOM时使用的编码):

Set-ContentAdd-Content默认为ANSI(Get-Content),与Import-PowerShellDataFile一致。

相比之下,DefaultSet-ContentImport-Csv在没有BOM的情况下采用UTF-8 - 与Import-CliXmlSelect-String

不同

答案 1 :(得分:2)

简而言之,使用:

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