使用PowerShell替换文本文件中的扩展ASCII字符

8

我需要在多个csv文件中将十六进制93字符替换为""字符串。以下是我使用的代码。但它不起作用,我认为原因是十六进制值大于7F(Dec 127)。我已尝试过其他几种方法,但都无济于事。任何帮助将不胜感激。

$q1 = [String](0x93 -as [char])
Get-ChildItem ".\*.csv" -Recurse | ForEach {
(Get-Content $_ | ForEach  { $_.replace($q1, '""') }) |
     Set-Content $_
}

注意:附上的是我测试文件格式的十六进制转储图像。第一个字符是我需要执行替换的字符:enter image description here
1个回答

13

在 Windows PowerShell 中,读取/写入文件时的默认字符编码为“ANSI”,即活动系统语言环境所隐含的旧的8位代码页。
(相比之下,PowerShell Core 的默认编码为 UTF-8。)

例如,在美式英语系统上与系统语言环境相关联的代码页是 1252,即 Windows-1252,其中代码点0x93是非ASCII的引号符“。

但是,一旦将文本文件的内容读入内存中,内存中 字符串的字符以 UTF-16LE 代码单元表示,也就是 .NET [string] 实例。

作为一个 Unicode 字符,“的”有代码点U+201c,在UTF-16LE中表示为 0x201c

因此,你需要替换的是 [char] 0x201c

$q1 = [char] 0x201c  # “
Get-ChildItem *.csv -Recurse | ForEach-Object {
  (Get-Content $_.FullName) -replace $q1, '""' | Set-Content $_.FullName
}
请注意,Set-Content也使用默认字符编码,因此重写的文件也将使用“ANSI”编码 - 如果需要更改输出编码,请使用-Encoding参数。
还要注意Get-Content调用周围的(...),这确保输入文件被完全读入内存,从而使在同一管道中向同一文件写回成为可能。虽然这种方法很方便,但请注意,在完成之前如果写回输入文件操作被中断,存在轻微数据丢失的风险。
将“ANSI”代码点转换为Unicode代码点 以下显示了如何将“ANSI”(8位)代码点(例如0x93)转换为其等效的UTF-16代码点0x201c
# Convert an array of "ANSI" code points (1 byte each) to the UTF-16
# string they represent. 
# Note: In Windows PowerShell, [Text.Encoding]::Default contains
#       the "ANSI" encoding set by the system locale.
$str = [Text.Encoding]::Default.GetString([byte[]] 0x93) # -> '“'

# Get the UTF-16 code points of the characters making up the string.
$codePoints = [int[]] [char[]] $str

# Format the first and only code point as a hex. number.
'0x{0:x}' -f $codePoints[0]  # -> '0x201c'

[1] 使用Set-Content编写文件,即使用Out-File / >则创建UTF-16LE(“Unicode”)文件。Windows PowerShell中的cmdlets显示了各种不同的编码:请参见此答案。幸运的是,PowerShell Core现在默认使用(无BOM)UTF-8。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接