在 PowerShell (Core) 7+ 中,默认情况下,你会得到无 BOM 的 UTF-8 文件;使用 -Encoding utf8 和 -Encoding utf8NoBom 可以明确表示默认值;要使用 BOM,需要使用 -Encoding utf8BOM。
在 Windows PowerShell 中,不幸的是,你必须使用一个解决方法来获取无 BOM 的 UTF-8,因为 -Encoding utf8 只会生成带有 BOM 的 UTF-8 文件(不支持其他 utf8 相关的值)。
这个解决方法需要将Out-String
与New-Item
结合起来,即使在Windows PowerShell中,默认情况下它会创建无BOM的UTF-8文件。
Param(
[string]$StrExpFile,
[string]$TargetWord,
[string]$ReplaceWord
)
$null =
New-Item -Force $StrExpFile -Value (
(Get-Content $StrExpFile).Replace($TargetWord, $ReplaceWord) | Out-String
)
注意:
$null =
需要丢弃New-Item
生成的输出对象(它是描述新创建的文件的文件信息对象)。
-Force
需要以静默方式覆盖同名的现有文件(与Set-Content
和Out-File
默认情况下相同)。
-Value
参数必须是要写入文件的单个(多行)字符串,这就是Out-String
确保的。
注意事项:
对于非字符串输入对象,Out-String创建与Out-File相同的丰富的显示表示,并且默认情况下在控制台中看到的也是如此。
New-Item本身在将字符串写入文件时不会追加尾随换行符,但是Out-String却会;虽然这在这里很方便,但通常会引起问题,如GitHub问题#14444中所讨论的那样。
使用Out-String的替代方法是手动创建多行字符串,这有点麻烦(在Windows上,PowerShell和大多数程序都可以接受使用"`n"创建仅包含LF的换行符;对于平台本地的换行符(CRLF),请改用[Environment]::NewLine):
由于整个文件内容必须作为参数传递,因此它必须作为一个整体适应内存;下面讨论的便利函数避免了这个问题。
对于一个在Windows PowerShell中使用的方便的包装函数,用于创建无BOM的UTF-8文件,请参阅
this answer。
替代方案,使用.NET APIs 直接操作:
默认情况下,.NET APIs 生成无BOM的UTF-8文件。然而,因为.NET的工作目录通常与PowerShell的不同,在使用时必须始终使用完整文件路径,这需要更多的努力:
$OutDir = Split-Path -Parent $StrExpFile
if ($OutDir -eq '') { $OutDir = '.' }
$strExpFileFullPath = Join-Path (Convert-Path $OutDir) (Split-Path -Leaf $StrExpFile)
[IO.File]::WriteAllLines(
$strExpFileFullPath,
(Get-Content $StrExpFile).Replace($TargetWord, $ReplaceWord)
)
以上使用了System.IO.File.WriteAllLines
方法。
请注意,虽然 New-Item
技术上支持通过 管道 接收要写入文件的内容,但不幸的是它会将每个值按顺序写入目标文件,只有最后一个值会出现在文件中。