默认情况下,当您将命令的输出重定向到文件或将其传递到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?
注意:以下内容适用于Windows PowerShell。有关跨平台PowerShell核心版本的信息,请参阅下一节。
>
和>>
实际上是Out-File
的别名,您可以通过>
首选项变量设置>>
/ Out-File
/ $PSDefaultParameterValues
的默认编码:
$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'
>
/ >>
的编码,但是,在PSv3或更高版本上,上述技术适用于调用Out-File
。
($PSDefaultParameterValues
偏好变量在PSv3.0中引入)。-Encoding
参数(在PSv5.1 +中包括>
和>>
),使用:
$PSDefaultParameterValues['*:Encoding'] = 'utf8'
如果将此命令放在$PROFILE
中,则Out-File
和Set-Content
等cmdlet默认情况下将使用UTF-8编码,但请注意,这使其成为会话全局设置,将影响未明确指定编码的所有命令/脚本。
同样,请确保在您希望以相同方式运行的脚本或模块中包含此类命令,以便即使在由其他用户或其他计算机运行时它们的行为也确实相同。
警告:PowerShell,从v5.1开始,总是使用(pseudo) BOM创建UTF-8文件,这在Windows世界中是惯用的 - 基于Unix的实用程序无法识别此BOM(参见底部)。
有关许多Windows PowerShell标准cmdlet中严重不一致的默认字符编码行为的摘要,请参阅底部。
自动$OutputEncoding
变量是不相关的,仅适用于PowerShell与外部程序通信的方式(PowerShell在向其发送字符串时使用的编码) - 它与输出重定向运算符和PowerShell cmdlet用于保存到文件的编码无关。
PowerShell is now cross-platform,通过其PowerShell Core版本,其编码 - 合理地 - 默认为无BOM的UTF-8,与类Unix平台一致。
>
/ Out-File
/ Set-Content
默认为无BOM的UTF-8;明确使用utf8
-Encoding
参数也会创建无BOM的UTF-8,但您可以选择使用带有utf8bom
值的伪BOM创建文件。*.ps1
文件通常不会具有UTF-8伪BOM:
这在PowerShell Core上运行良好。
如果文件包含非ASCII字符,它可能会在Windows PowerShell上中断;如果您确实需要在脚本中使用非ASCII字符,请将它们保存为带有BOM的UTF-8。
如果没有BOM,Windows PowerShell(mis)会将您的脚本解释为在旧版“ANSI”代码页中进行编码(由Unicode前应用程序的系统区域设置决定;例如,美英系统上的Windows-1252)。cat
,sed
和awk
等Unix实用程序 - 甚至某些编辑器(如gedit
)传递伪BOM通过,即将其视为数据。
这可能并不总是一个问题,但绝对可以,例如当您尝试将文件读入bash
中的字符串时,例如text=$(cat file)
或text=$(<file)
- 结果变量将包含伪BOM作为前3个字节。遗憾的是,Windows PowerShell中使用的默认字符编码非常不一致;正如前一节所讨论的,跨平台的PowerShell核心版本已经值得称道地说明了这一点。
注意:
编写的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文件,如文档所述,但请参阅下面的注释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-Content
和this 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-Content
和Import-PowerShellDataFile
默认为ANSI(Default
),这与Set-Content
一致。
相比之下,Import-Csv
,Import-CliXml
和Select-String
假设没有BOM的UTF-8 - 不像Get-Content
和Import-PowerShellDataFile