powershell 无BOM的写入输出

xzabzqsa  于 2023-04-06  发布在  Shell
关注(0)|答案(2)|浏览(234)

如果我运行这样的命令:

Write-Output March > a.txt

我得到这个结果:

U+FEFF    
M       U+004D          
a       U+0061          
r       U+0072    
c       U+0063          
h       U+0068 
        U+000D       
\n      U+000A

我不想要BOM。我尝试了不同的操作,如下所示:

$OutputEncoding = [System.Text.UTF8Encoding]::new($false)
$PSDefaultParameterValues['*:Encoding'] = 'utf8'
[Console]::InputEncoding = [System.Text.UTF8Encoding]::new($false)
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)

但它们似乎都没有解决这个问题。注意我正在使用PowerShell 5. 1。我确实看到了一些类似的问题,但与此不完全相同,因为它们是在处理管道和外部命令。

ac1kyiln

ac1kyiln1#

TL;医生

  • 如果您希望 Windows PowerShell>运算符和Out-File等cmdlet输出 * 无BOM * UTF-8,唯一的选择是更改为该编码 * 系统范围 *(请参阅下一节中的警告):
  • 作为 * 一次性步骤 *,运行intl.cpl打开控制面板的区域设置,切换到Administrative选项卡,单击Change system locale...按钮并选中Beta: Use Unicode UTF-8 for worldwide language support。需要重新启动。
    • 另外 *,在每个会话 * 中运行以下 *,最好通过$PROFILE文件完成:
  • $PSDefaultParameterValues['*:Encoding'] = 'Default'
  • 否则,您必须直接使用.NET API(参见this question的答案),或者围绕它们编写一个PowerShell友好的 Package 器(参见this answer,其中还显示了New-Item的替代方案)。
  • 或者您也可以安装跨平台的**PowerShell (Core) v6+版本**,默认为无BOM的UTF-8
    从Windows 10开始,您可以将Windows PowerShell * 默认设置为无BOM的UTF-8 -假设您愿意更改为此编码 * 系统范围
    *将系统区域设置(非Unicode程序的语言)更改为无BOM的UTF-8,如this answer中所述:
  • 简而言之:运行intl.cpl打开控制面板的区域设置,切换到Administrative选项卡,点击Change system locale...按钮,勾选Beta: Use Unicode UTF-8 for worldwide language support;请注意,您需要 * 管理员权限 * 来进行此更改,并且需要 * 重新启动 * 才能使更改生效。
    *注意事项
  • 此更改将OEM和ANSI代码页都设置为65001,即(无BOM)UTF-8,这**不仅影响 * 所有控制台窗口 ,而且影响 * 所有遗留(非Unicode)应用程序 ,包括GUI应用程序
  • 截至Windows 11版本22 H2,此功能 * 仍处于测试阶段 *,可能会破坏传统的控制台应用程序。
  • 然后,在Windows PowerShell v5.1中,**将以下内容添加到$PROFILE**文件中(在PowerShell(Core)v6+中不需要):
  • $PSDefaultParameterValues['*:Encoding'] = 'Default'
  • $OutputEncoding = [System.Text.Utf8Encoding]::new($false)

这样做的结果是:

  • 所有具有-Encoding参数的文件写入[1] Windows PowerShell cmdlet将默认为无BOM-less UTF-8(Default表示活动ANSI代码页,然后将是65001,即无BOM-less UTF-8)-特别是包括>/Out-File/Set-Content
  • 然后Windows PowerShell也会 * 读取 * 无BOM文件作为UTF-8,包括 * 源代码 * 和通过Get-Content;通常,Windows PowerShell基于 * 系统区域设置适当的ANSI* 代码页解释无BOM文件(而PowerShell(Core)v6+假定为UTF-8)。
  • 由于OEM代码页是无BOM的UTF-8(如chcp.com报告65001所反映的),PowerShell也将使用无BOM的UTF-8:
  • 解释通过其CLI从外部接收的数据时。
  • 在PowerShell会话中解释从外部程序接收的数据时。
  • 上面的$OutputEncoding赋值还确保PowerShell将数据作为无BOM的UTF-8发送给外部程序。(幸运的是,这个首选项变量现在在PowerShell [Core] v6+中默认为无BOM的UTF-8。)

请注意,上述内容还使所有 PowerShell [Core] v6+ 控制台窗口在所有方面都使用无BOM的UTF-8,除了您不需要$PROFILE添加(尽管它们没有害处)。

背景资料

  • > a.txt实际上与| Out-File a.txt相同。
    Windows PowerShell的>/>>/Out-File * 默认为UTF-16 LE(“Unicode”)[2],它总是使用BOM。
  • 您有两个选项用于选择不同的编码
  • 显式使用Out-File * 并使用其-Encoding参数。
  • 在v5.1(以及PowerShell [Core] v6+)中,您可以通过$PSDefaultParameterValues首选项变量设置>/>>/Out-File的默认编码,如this answer中所述。
    ***但是,在 Windows PowerShell 中,-Encodingutf8值 * 始终 * 是带有BOM***的UTF-8编码 *,因此-除非您愿意切换到UTF-8 * 系统范围 *,如上所述-创建 * 无BOM * UTF-8文件的唯一方法是 * 直接使用.NET API *。
  • 请注意,在 PowerShell [Core] v6+ 中,-Encoding参数所接受的utf8值现在(更明智地)引用 BOM-less UTF-8编码;如果您确实需要UTF-8 BOM,请使用utf8BOM

至于你所尝试的

*您尝试的属性和变量仅与PowerShell(在两个版本中)与外部程序 * 通信的方式有关

  • $OutputEncoding确定PowerShell通过管道 * 向外部程序 * 发送数据时使用的编码(后者可以通过stdin(标准输入)读取)。

  • [Console]::OutputEncoding确定PowerShell在解释 * 从外部程序 * 接收的输出时使用的编码。

  • [Console]::InputEncoding是PowerShell在 it 从外部 * 接收数据 * 时使用的编码,当调用其CLI时。

  • 警告:在这种情况下,您不能从PowerShell会话中更改此编码,因为那将为时已晚。

  • 它必须由 * 调用者 * 在 * 调用PowerShell CLI之前设置,从cmd.exe调用PowerShell CLI最容易使用chcp 65001完成(请参见下面关于从 * 内部 * PowerShell调用chcp的警告)。虽然这总是同时设置 * [Console]::InputEncoding[Console]::OutputEncoding,但这通常是可取的。

注意事项:

  • 在Windows上,默认情况下,[Console]::OutputEncoding[Console]::InputEncoding反映旧系统区域设置的OEM代码页的编码,如chcp.com所报告的;在类Unix平台(PowerShell [Core] v6+)上,它是(现在几乎无一例外)(无BOM)UTF-8
  • 由于这些.NET属性中的编码的 * 缓存 *,您无法从 inside PowerShell使用chcp.com来更改这些属性-而是直接分配所需的编码。
  • 有关详细信息,请参阅this answer,其中讨论了如何使Windows上的控制台窗口在外部程序 * 方面始终使用无BOM的UTF-8。

[1]从技术上讲,此首选项也适用于file-* 阅读 * cmdlet,这对于无BOM的文件来说不是绝对必要的,对于 * 具有 * BOM的文件也没有任何危害-即使该BOM指示UTF-16或UTF-32编码-因为BOM总是覆盖-Encoding参数。
[2]不幸的是,在Windows PowerShell中,默认编码在cmdlet中变化很大-请参阅this answer的底部部分。

odopli94

odopli942#

如果你只使用ascii字符,在powershell5.1中set-content就可以了:

Write-Output March | set-content a.txt
'March' | set-content a.txt

或者在你的$profile中使用这个哈希表将out-file的默认编码设置为ascii。out-file的默认编码是utf 16或'unicode'编码。'〉'是out-file的快捷方式。键的名称必须用引号括起来,因为它包含冒号。utf8 nobom直到以后的powershell版本才可用。'〉〉'也会调用out-file,并且可能会在同一个文件中混合编码。

$PSDefaultParameterValues = @{ 'out-file:encoding' = 'ascii' }

这将创建一个ascii文件:

Write-Output March > a.txt

相关问题