默认情况下,当您将命令的输出重定向到文件或将其通过管道传输到 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'}
设置输出编码,但我试过了,没有效果。
谈到 $OutputEncoding
的 https://blogs.msdn.microsoft.com/powershell/2006/12/11/outputencoding-to-the-rescue/ 乍一看似乎应该是相关的,但随后它谈到了以 ASCII 编码的输出,这并不是实际发生的事情。
如何将 PowerShell 设置为使用 UTF-8?
笔记:
下一部分主要适用于 Windows PowerShell。有关跨平台 PowerShell Core (v6+) 版本,请参阅其后面的部分。
有关跨平台 PowerShell Core (v6+) 版本,请参阅其后面的部分。
在这两种情况下,这些信息都适用于使 PowerShell 使用 UTF-8 来读取和写入文件。相比之下,有关如何与外部程序发送和接收 UTF-8 编码字符串的信息,请参阅此答案。
相比之下,有关如何与外部程序发送和接收 UTF-8 编码字符串的信息,请参阅此答案。
在 PSv5.1 或更高版本中,其中 > 和 >> 是 Out-File 的有效别名,您可以通过 $PSDefaultParameterValues 首选项变量为 > / >> / Out-File 设置默认编码: $PSDefaultParameterValues['Out-File: Encoding'] = 'utf8' 注意:在 Windows PowerShell(最新和最终版本为 v5.1 的旧版本)中,这总是会创建带有(伪)BOM 的 UTF-8 文件。许多基于 Unix 的实用程序无法识别此 BOM(见底部);有关创建无 BOM 的 UTF-8 文件的解决方法,请参阅此帖子。在 PowerShell (Core) v6+ 中,无 BOM 的 UTF-8 是默认设置(请参阅下一节),但如果您确实需要 BOM,则可以使用“utf8BOM”
$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'
注意:在 Windows PowerShell(最新和最终版本为 v5.1 的旧版)中,这总是会创建带有(伪)BOM 的 UTF-8 文件。许多基于 Unix 的实用程序无法识别此 BOM(见底部);有关创建无 BOM 的 UTF-8 文件的解决方法,请参阅此帖子。在 PowerShell (Core) v6+ 中,无 BOM 的 UTF-8 是默认设置(请参阅下一节),但如果您确实需要 BOM,则可以使用“utf8BOM”
在 Windows PowerShell(最新和最终版本为 v5.1 的旧版)中,这总是会创建带有(伪)BOM 的 UTF-8 文件。许多基于 Unix 的实用程序无法识别此 BOM(见底部);有关创建无 BOM 的 UTF-8 文件的解决方法,请参阅此帖子。
许多基于 Unix 的实用程序无法识别此 BOM(见底部);有关创建无 BOM 的 UTF-8 文件的解决方法,请参阅此帖子。
在 PowerShell (Core) v6+ 中,无 BOM 的 UTF-8 是默认设置(请参阅下一节),但如果您确实需要 BOM,则可以使用“utf8BOM”
在 PSv5.0 或更低版本中,您无法更改 > / >> 的编码,但在 PSv3 或更高版本中,上述技术确实适用于对 Out-File 的显式调用。 (PSv3.0 中引入了 $PSDefaultParameterValues 首选项变量)。
在 PSv3.0 或更高版本中,如果要为所有支持 -Encoding 参数(在 PSv5.1+ 中包括 > 和 >>)的 cmdlet 设置默认编码,请使用:$PSDefaultParameterValues['*:Encoding'] = 'utf8'
$PSDefaultParameterValues['*:Encoding'] = 'utf8'
如果将此命令放在您的 $PROFILE
中,则 如 Out-File
和 Set-Content
等 cmdlet 将默认使用 UTF-8 编码,但请注意,这使得它会话全局设置,它将影响所有未通过其 -Encoding
参数明确指定编码的命令/脚本。
同样,请务必在您的 脚本 或 模块 中包含您希望以相同方式运行的命令,以便它们的行为确实相同即使由另一个用户或不同的机器运行;但是,为避免会话-全局更改,请使用以下表单创建 $PSDefaultParameterValues
的本地副本:
$PSDefaultParameterValues = @{ '*:Encoding' = 'utf8' }
有关许多 Windows PowerShell 标准 cmdlet 中非常不一致的默认字符编码行为的摘要,请参阅底部部分。
自动 $OutputEncoding
变量不相关,仅适用于 PowerShell 与外部程序的通信方式(PowerShell 在向它们发送字符串时使用的编码) - 它与输出重定向运算符和 PowerShell cmdlet 用于保存到文件的编码无关。
可选阅读:跨平台视角:PowerShell Core:
PowerShell is now cross-platform,通过其 PowerShell Core 版本,其编码 - 明智地 - 默认为 BOM-less 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(错误)会将您的脚本解释为在旧版“ANSI”代码页中编码(由 Unicode 前应用程序的系统区域设置确定;例如,美国英语系统上的 Windows-1252)。
这在 PowerShell Core 上运行良好。
如果文件包含非 ASCII 字符,它可能会在 Windows PowerShell 上中断;如果您确实需要在脚本中使用非 ASCII 字符,请将它们保存为带有 BOM 的 UTF-8。如果没有 BOM,Windows PowerShell(错误)会将您的脚本解释为在旧版“ANSI”代码页中编码(由 Unicode 前应用程序的系统区域设置确定;例如,美国英语系统上的 Windows-1252)。
相反,具有 UTF-8 伪 BOM 的文件在类 Unix 平台上可能会出现问题,因为它们会导致诸如 cat、sed 和 awk 之类的 Unix 实用程序——甚至是诸如 gedit 之类的一些编辑器——传递伪 BOM通过,即,将其视为数据。这可能并不总是一个问题,但绝对可以,例如当您尝试使用 text=$(cat file) 或 text=$(
这可能并不总是一个问题,但绝对可以,例如当您尝试使用 text=$(cat file) 或 text=$(
Windows PowerShell 中的默认编码行为不一致:
遗憾的是,Windows PowerShell 中使用的默认字符编码非常不一致;正如上一节所讨论的,跨平台的 PowerShell Core 版本已经很好地结束了这一点。
笔记:
以下内容并不打算涵盖所有标准 cmdlet。
谷歌搜索 cmdlet 名称以查找其帮助主题现在默认显示主题的 PowerShell Core 版本;使用左侧主题列表上方的版本下拉列表切换到 Windows PowerShell 版本。
在撰写本文时,文档经常错误地声称 ASCII 是 Windows PowerShell 中的默认编码 - 请参阅此 GitHub 文档问题。
写入以下内容的 Cmdlet:
重新附加到现有文件的命令:
读取(即在没有 BOM 时使用的编码)的 Cmdlet:
相比之下,Out-File
和 >
/ >>
创建“Unicode” - UTF-16LE - 默认情况下的文件 - 其中每个 ASCII 范围字符(也)由 2 个字节表示 - 这明显不同从 Set-Content
/ Add-Content
(见下一点); New-ModuleManifest
和 Export-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-less(!) UTF-8。
Send-MailMessage
帮助主题还声称 ASCII 编码是默认值 - 我没有亲自验证该声明。
Start-Transcript
总是 创建 UTF-8 文件 BOM,但请参阅下面关于 -Append
的注释。
>>
/ Out-File -Append
使 no 尝试匹配文件的现有内容 的编码。也就是说,它们盲目地应用默认编码,除非使用 -Encoding
另有指示,这不是 >>
的选项(在 PSv5.1+ 中通过 $PSDefaultParameterValues
间接除外,如上所示)。简而言之:您必须知道现有文件内容的编码并使用相同的编码追加。
Add-Content
是一个值得称赞的例外:在没有显式 -Encoding
参数的情况下,它会检测现有编码并自动将其应用于新内容。谢谢,js2010。请注意,在 Windows PowerShell 中,这意味着如果现有内容没有 BOM,则应用 ANSI 编码,而在 PowerShell Core 中应用的是 UTF-8。
Out-File -Append
/ >>
和 Add-Content
之间的这种不一致也会影响 PowerShell Core,在 this GitHub issue 中进行了讨论。
Export-Csv -Append
部分 匹配现有编码:如果现有文件的编码是 ASCII/UTF-8/ANSI 中的任何一种,但正确匹配 UTF- 16LE 和 UTF-16BE。
换一种说法:在没有 BOM 的情况下,Export-Csv -Append
假定 UTF-8 是,而 Add-Content
假定 ANSI。
Start-Transcript -Append
部分 匹配现有编码:它正确匹配编码与 BOM,但在没有编码的情况下默认为可能有损的 ASCII 编码。
Get-Content
和 Import-PowerShellDataFile
默认为 ANSI (Default
),这与 Set-Content
一致。
ANSI 也是 PowerShell 引擎在读取 源代码 时本身的默认值文件。
Import-Csv
、Import-CliXml
和 Select-String
在没有 BOM 的情况下采用 UTF-8。
简而言之,使用:
write-output "your text" | out-file -append -encoding utf8 "filename"
您可能希望将部分脚本放入大括号中,以便可以重定向几个命令的输出:
{
command 1
command 2
} | out-file -append -encoding utf8 "filename"
>foo.txt
语法替换为 | out-file foo.txt -encoding utf8
来逐案完成,但每次都必须重复这很尴尬。”换句话说:您正是在暗示 OP 试图避免的事情。
-append
应该被删除
不定期副业成功案例分享
$PSDefaultParameterValues