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

How to set encoding for a herestring/heredoc in powershell?

我正在尝试更新 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”的方法来做到这一点,我将不胜感激 input/suggestions.

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

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

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

>> file 实际上与 | Out-File -Append file 相同,并且在 Windows PowerShell Out-File 默认为 UTF16-LE 编码(“Un​​icode”),其中每个字符(通常)用 2 个字节 编码。看起来是空格的实际上是每个 ASCII 范围字符编码的第 2 个字节中的 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 匹配 文件预先存在的内容的编码(并且,如果有 none,则默认为Windows PowerShell 中的活动 ANSI 代码页编码(“默认”),如 Set-Content);在没有 BOM 的情况下,如在本例中,假定使用 ANSI 编码,但使用仅 ASCII 范围的输入字符实际上与 ASCII 相同,因为 ANSI 代码页是 ASCII 的超集。


另请参阅:

  • 一个密切相关的问题。

  • ,包括如何更改 > / >>.

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

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