用以下解决方案补充Mathias R. Jessen's helpful answer:
# Explicitly read the input files as UTF-8, as a whole.
$content = get-content -raw -encoding utf8 test.html
$template = get-content -raw -encoding utf8 template.html
# Write to output file using UTF-8 encoding *without a BOM*.
[IO.File]::WriteAllText(
"$PWD/out.html",
$ExecutionContext.InvokeCommand.ExpandString($template)
)
-
get-content -raw (PSv3+) 将作为一个整体中的文件读取到一个单个字符串中(而不是字符串的数组,逐行),虽然更占用内存,但速度更快。对于 HTML 文件,内存使用不应该成为问题。
- 完整读取文件的另一个优点是,如果模板包含 多行 子表达式 (
$(...)),则扩展仍然可以正常工作。
-
get-content -encoding utf8 确保输入文件被解释为使用字符编码 UTF-8,这在当今网络世界中很常见。
- 这是至关重要的,因为 UTF-8 编码的 HTML 文件通常不具有 PowerShell 正确识别文件为 UTF- 所需的 3 字节伪 BOM 8 位编码(见下文)。
然后一个$ExecutionContext.InvokeCommand.ExpandString() 调用就足以执行模板扩展。
-
Out-File -Encoding utf8 总是会使用伪 BOM 创建一个文件,这是不受欢迎的。
而是使用 [IO.File]::WriteAllText(),利用 .NET Framework默认创建 UTF-8 编码文件BOM.
- 注意
$PWD/ 在out.html 之前的使用,这是确保文件写入PowerShell 的当前位置(目录)所必需的;不幸的是,.NET Framework 认为当前目录不与 PowerShell 同步。
最后,强制性安全警告:仅在您信任的输入上使用此扩展技术,因为可能会执行任意嵌入式命令。
可选的背景信息
PowerShell 的Out-File、> 和>> 默认使用UTF-16 LE 字符编码和BOM (byte-order mark)(“奇怪的字符”,如前所述)。
虽然 Out-File -Encoding utf8 允许创建 UTF-8 输出文件,
PowerShell总是在输出文件前添加一个 3 字节的 pseudo-BOM,一些实用程序,尤其是那些具有 Unix 传统的实用程序存在问题 - 所以您仍会得到“奇怪的字符”(尽管不同)。
如果您想要以更类似于 PowerShell 的方式创建无 BOM 的 UTF-8 文件,
请参阅我的 this answer,它定义了一个 Out-FileUtf8NoBom 函数,该函数模拟了 Out-File 的核心功能。
相反,在读取文件时,您必须使用Get-Content -Encoding utf8 来确保无BOM 的UTF-8 文件能够被识别。
在没有 UTF-8 伪 BOM 的情况下,Get-Content 假定文件使用系统的旧代码页 指定的单字节扩展 ASCII 编码(例如,@ 987654328@ 在英语语言系统上,PowerShell 调用 Default 的编码)。
请注意,当仅 Windows 的编辑器(例如记事本)创建 UTF-8 文件时,使用伪 BOM(如果您明确选择另存为 UTF-8;默认是传统代码页编码,“ANSI”),越来越流行的跨平台编辑器,例如 Visual Studio Code、Atom 和 Sublime Text 默认情况下不使用伪 BOM当他们创建文件时。