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

fkaflof6  于 2023-01-13  发布在  Shell
关注(0)|答案(3)|浏览(311)

默认情况下,当您将命令的输出重定向到一个文件或通过管道将其传输到PowerShell中的其他内容时,编码是UTF-16,这没有什么用。
这可以通过将>foo.txt语法替换为| out-file foo.txt -encoding utf8来逐个执行,但每次都要重复这一操作是很尴尬的。
在PowerShell中设置内容的持久方法是将它们放在\Users\me\Documents\WindowsPowerShell\profile.ps1中;我已经验证了这个文件确实在启动时执行。
据说输出编码可以用$PSDefaultParameterValues = @{'Out-File:Encoding' = 'utf8'}设置,但我试过了,没有效果。
谈到$OutputEncodinghttps://blogs.msdn.microsoft.com/powershell/2006/12/11/outputencoding-to-the-rescue/乍一看似乎应该是相关的,但随后它谈到输出是用ASCII编码的,这不是实际发生的事情。
如何将PowerShell设置为使用UTF-8?

nx7onnlm

nx7onnlm1#

注:

      • 下一节主要适用于 * Windows PowerShell***。
  • 跨平台**PowerShell Core (v6+)版本见*后**节。
  • 在这两种情况下,信息都适用于使PowerShell使用UTF-8读写 * 文件*。
  • 相比之下,有关如何向 * 外部程序发送UTF-8编码的 * 字符串 * 以及从 * 外部程序**接收UTF-8编码的 * 字符串 * 的信息,请参见this answer
      • 现在可以在 * 系统范围内 * 切换到UTF-8**(自Windows 10的最新版本以来):请参见this answer,但请注意以下警告
  • 该特性具有深远的影响,因为OEM和ANSI代码页都被设置为65001,即UTF-8;同样,在撰写本文时,该特征仍被认为是 * beta * 特征。
  • 在 * Windows PowerShell * 中,这仅对默认为ANSI代码页的cmdlet有效,特别是Set-Content,但 * 不适用于 * Out-File/>,它还适用于 * 读取 * 文件,特别是包括Get-Content以及PowerShell本身读取 * 源代码 * 的方式。
* Windows PowerShell * 透视图:
  • PSv5.1或更高版本中,其中>>>实际上是Out-File的别名,您可以通过$PSDefaultParameterValues首选项变量设置>/>>/Out-File的默认编码:
  • $PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'
  • 注:
  • Windows PowerShell***(最新和最终版本为v5.1的旧版)中,此总是创建带有(伪)BOM**的UTF-8文件。
  • 许多基于 * Unix * 的实用程序无法识别此BOM(见底部);有关创建无BOM的UTF-8文件的解决方法,请参见this post
      • 在 * PowerShell(Core)v6 +* 中,* 默认值为 * UTF-8***(请参见下一节),但如果您 * 确实 * 需要BOM,则可以使用'utf8BOM'
  • PSv5.0或更低版本中,您无法 * 更改>/>>的编码,但在PSv3或更高版本中,上述技术可 * 用于显式调用Out-File

(The PSv3.0中引入了$PSDefaultParameterValues偏好变量)。

  • PSv3.0或更高版本中,如果要**为支持的 * 所有 * cmdlet设置默认编码

-Encoding参数**(在PSv5.1及以上版本中包括>>>),请使用:

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

类似地,确保在您的 * 脚本 * 或 * 模块 * 中包含您希望以相同方式运行的命令,以便即使由另一个用户或不同的机器运行时,它们也确实具有相同的行为;但是,为避免会话-* global * 更改,请使用以下格式创建$PSDefaultParameterValues的 * local * 拷贝:

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

有关许多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-less * 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字符,请将它们保存为UTF-8 * 和BOM *。

如果没有BOM,Windows PowerShell(mis)会将您的脚本解释为以旧版"ANSI"代码页编码(对于Unicode之前的应用程序,由系统区域设置确定;例如,美国英语系统上的Windows-1252)。

  • 相反,* do * 具有UTF-8伪BOM的文件在类Unix平台上可能会有问题,因为它们会导致Unix实用程序(如catsedawk),甚至一些编辑器(如gedit)* 通过 * 传递伪BOM,即将其视为 * data *。
  • 这可能并不总是一个问题,但肯定是一个问题,例如当您尝试将一个文件读入bash的字符串(比如text=$(cat file)text=$(<file))时,结果变量将包含伪BOM作为前3个字节。

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

遗憾的是,WindowsPowerShell中使用的默认字符编码非常不一致;如前一节所述,跨平台的PowerShell * Core * 版已经彻底解决了这一问题。
注:

  • 以下内容并不打算涵盖 * 所有 * 标准cmdlet。
  • Google cmdlet名称以查找其帮助主题,现在默认情况下会显示主题的PowerShell * Core * 版本;使用左侧主题列表上方的版本下拉列表切换到 * Windows PowerShell * 版本。
  • 历史上,文档经常错误地声称ASCII是Windows PowerShell中的默认编码;幸运的是,这一点后来得到了纠正。
    • 写入 * 的命令:**

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文件,如文档所示,但请参见下面有关-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编码。
Out-File -Append/>>Add-Content之间的这种不一致性也会影响PowerShell * Core *,在GitHub问题#9423中讨论。
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(即,在 * 没有BOM * 的情况下使用的编码):

Get-ContentImport-PowerShellDataFile默认为ANSI(Default),这与Set-Content一致。
ANSI也是PowerShell引擎从文件读取 * 源代码 * 时的默认值。
相比之下,Import-CsvImport-CliXmlSelect-String在没有BOM的情况下采用UTF-8。

mrwjdhj3

mrwjdhj32#

简而言之,请用途:

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

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

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

vnjpjtjt3#

在Windows上使用PowerShell进行输出重定向的转储会创建一个采用UTF-16编码的文件。要解决此问题,你可以尝试:

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

参考链接:mysqldump_结果文件

相关问题