如何在powershell中为herestring/heredoc设置编码?

Posted

技术标签:

【中文标题】如何在powershell中为herestring/heredoc设置编码?【英文标题】:How to set encoding for a herestring/heredoc in powershell? 【发布时间】:2019-12-23 04:50:49 【问题描述】:

我正在尝试更新 Windows 服务器上的主机文件,并尝试使用 powershell 中的 heredoc 进行更新。

我无法弄清楚为什么我的结果在每个主机条目中的每个字符之间都有额外的空格。

我正在从 Linux 移植一些脚本。

PS C:\Users\Administrator> cat C:\Users\Administrator\AppData\Local\Temp\etchosts.ps1
@"
127.0.0.1 src.example.com
127.0.0.2 builds.example.com
127.0.0.3 ti.example.com
127.0.0.4 jira.example.com
"@ >>C:\Windows\System32\drivers\etc\hosts



PS C:\Users\Administrator> powershell C:\Users\Administrator\AppData\Local\Temp\etchosts.ps1
PS C:\Users\Administrator> cat C:\Windows\System32\drivers\etc\hosts
# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host

# localhost name resolution is handled within DNS itself.
#       127.0.0.1       localhost
#       ::1             localhost
 1 2 7 . 0 . 0 . 1   s r c . e x a m p l e . c o m

 1 2 7 . 0 . 0 . 2   b u i l d s . e x a m p l e . c o m

 1 2 7 . 0 . 0 . 3   t i . e x a m p l e . c o m

 1 2 7 . 0 . 0 . 4   j i r a . e x a m p l e . c o m

我希望所有字符之间没有空格。 如果有“Windows”方式可以做到这一点,我将不胜感激任何输入/建议。

【问题讨论】:

>> -> | Out-File -Encoding ASCII -Append 【参考方案1】:

here-string 只是 PowerShell 字符串文字的一种特殊形式,与 PowerShell 和 .NET (System.String) 中的 all 字符串一样,它们的内存编码始终是 UTF-16。

顺便说一句:要正确将字符串文字读入内存,必须正确编码封闭的脚本文件;最好的选择是带有 BOM 的 UTF-8 - 请参阅 this answer。

但是,重要的是如何将(内存中的)字符串写入文件

>> file 实际上与 | Out-File -Append file 相同,并且在 Windows PowerShellOut-File 默认为 UTF16-LE 编码(“Un​​icode”) ,其中每个字符(通常)用 2 个字节 编码。看似空格的东西实际上是每个 ASCII 范围字符编码的第二个字节中的 NUL (0x0) 字节。

顺便说一句:在 PowerShell Core 中,无 BOM 的 UTF-8 是 - 更明智的 - 默认值;由于 UTF-8 向后兼容 ASCII 范围内的字符,因此您的代码可以在 PowerShell Core 中正常运行。

相比之下,C:\Windows\System32\drivers\etc\hosts 是 ASCII 编码的(每个字符 1 个字节)。

要匹配该编码,使用Add-Content 而不是>>

@"
127.0.0.1 src.example.com
127.0.0.2 builds.example.com
127.0.0.3 ti.example.com
127.0.0.4 jira.example.com
"@ | Add-Content C:\Windows\System32\drivers\etc\hosts

Out-File -Append 不同,Add-Content 匹配文件预先存在的内容的编码(如果没有,则默认为 Windows PowerShell 中活动 ANSI 代码页的编码(“默认”) ,比如Set-Content);在没有 BOM 的情况下,在这种情况下,假定为 ANSI 编码,但由于 ANSI 代码页是 ASCII 的超集,因此使用与 ASCII 实际上相同的仅 ASCII 范围输入字符。


另见:

This answer 回答一个密切相关的问题。

This comprehensive overview of PowerShell's encoding behaviors,包括如何更改>/>>的默认编码。

This GitHub suggestion 将有关字符编码的概念性帮助主题添加到官方 PowerShell 文档中。

【讨论】:

我觉得我们需要把你最好的、最彻底的关于编码的帖子贴在某个地方。这出现了很多。 谢谢,@AdminOfThings。理想情况下,官方文档应该提供这些信息,并且有一个open suggestion to add that。与此同时,this answer 可能提供了最全面的概述。 谢谢。这真的很有帮助。我正要走安装wsl的道路,但由于这是一个配置aws实例的脚本,安装需要重新启动,这使事情变得复杂。我确实有一个相关的问题。我在实例的用户数据中有这个代码:@' .sshconfig '@ >C:\ProgramData\ssh\sshd_config ... 这似乎有正确的编码,你知道为什么吗? (.sshconfig 被替换) @mikedoy:很高兴听到这个消息。如果您使用 PowerShell Core,或者在 Windows PowerShell v5.1 中,如果您全局更改了 > 的编码,>C:\ProgramData\ssh\sshd_config 只能按预期工作(仅使用 ASCII 范围字符。)转换为 ASCII 或 ANIS(“默认”),如 this answer 所示。【参考方案2】:

我永远不会使用“out-file -append”或“>>”。它不检查当前编码是什么。这是 powershell 5 的一个可怕特性。现在你有一个混合了 ascii 和 unicode 的文件。空格实际上是空值。在这种情况下,我更喜欢添加内容。 Add-content 会先检查 BOM。

【讨论】:

以上是关于如何在powershell中为herestring/heredoc设置编码?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Powershell 中为“网络服务”帐户创建 Windows 服务?

如何从 powershell 中为 bash 设置环境变量?

powershell 在PowerShell中为Azure RM Terraform设置环境变量

PowerShell:在Windows 10中为Wi-Fi网络生成QR代码

使用 PowerShell 自动登录Azure

使用 PowerShell 自动登录 Azure