我正在使用AHK脚本将当前的剪贴板内容转储到一个文件中(该文件包含微软OneNote页面的一部分副本到一个文件)。
我想修改这个二进制文件,以搜索一个特定的字符串,并能够将它导入AHK。
我尝试了以下操作,但看起来powershell正在执行文件之外的其他操作(比如更改编码),而将文件导入剪贴板失败了。
$ThisFile = 'B:\Users\Desktop\onenote-new-entry.txt'
$data = Get-Content $ThisFile
$data = $data.Replace('asdf','TESTREPLACE!')
$data | Out-File -encoding utf8 $ThisFile
对于在不改变现有编码的情况下对文件执行字符串替换,有任何建议吗?
我尝试在文本编辑器中手动修改,它运行良好。显然,虽然我想让修改大量和自动完成,这就是为什么我需要一个脚本。
从OneNote复制并通过AHK转储到文件中的文本如下所示:
但是,注意剪贴板转储文件有很多其他元数据,在编辑器中打开时如下所示。要下载用于PS的测试,单击此处:
发布于 2022-09-20 19:41:41
由于您的文件是二进制数据和UTF-8文本的 mix ,所以不能使用 text 处理(正如您尝试使用Out-File -Encoding utf8
),因为二进制数据也总是被解释为文本,从而导致其损坏。
PowerShell不提供编辑二进制文件的简单方法,但是可以通过文件字节的辅助“十六进制字符串”表示来解决问题
# To compensate for a difference between Windows PowerShell and PowerShell (Core) 7+
# with respect to how byte processing is requested: -Encoding Byte vs. -AsByteStream
$byteEncParam =
if ($IsCoreCLR) { @{ AsByteStream = $true } }
else { @{ Encoding = 'Byte' } }
# Read the file *as a byte array*.
$ThisFile = 'B:\Users\Desktop\onenote-new-entry.txt'
$data = Get-Content @byteEncParam -ReadCount 0 $ThisFile
# Convert the array to a "hex string" in the form "nn-nn-nn-...",
# where nn represents a two-digit hex representation of each byte,
# e.g. '41-42' for 0x41, 0x42, which, if interpreted as a
# single-byte encoding (ASCII), is 'AB'.
$dataAsHexString = [BitConverter]::ToString($data)
# Define the search and replace strings, and convert them into
# "hex strings" too, using their UTF-8 byte representation.
$search = 'asdf'
$replacement = 'TESTREPLACE!'
$searchAsHexString = [BitConverter]::ToString([Text.Encoding]::UTF8.GetBytes($search))
$replaceAsHexString = [BitConverter]::ToString([Text.Encoding]::UTF8.GetBytes($replacement))
# Perform the replacement.
$dataAsHexString = $dataAsHexString.Replace($searchAsHexString, $replaceAsHexString)
# Convert he modified "hex string" back to a byte[] array.
$modifiedData = [byte[]] ($dataAsHexString -split '-' -replace '^', '0x')
# Save the byte array back to the file.
Set-Content @byteEncParam $ThisFile -Value $modifiedData
注意:
é
)-只工作如果输入类字符串文字在.NET -使用合成Unicode规范化形式,其中é
是一个单一的代码点,并编码为这样(结果是多字节UTF-8转义序列)。可选读取:修改UTF-8文件,不附带修改:
注意:
PowerShell从不保留有关输入文件字符编码的信息,例如用Get-Content
读取的文件。另外,除非使用-Raw
,否则将丢失有关特定换行符格式的信息,以及该文件是否有尾随换行符。
假设您知道编码:
Get-Content -Raw
读取文件,并使用-Encoding
指定编码(如果有必要)。您将以单行多行.NET字符串的形式接收文件的内容。Set-Content
-NoNewLine
将修改后的字符串保存回文件,使用原始编码的-Encoding
。- Caveat: In _Windows PowerShell_, `-Encoding utf8` invariably creates a UTF-8 file _with BOM_, unlike in _PowerShell (Core) 7+_, which _defaults_ to BOM-less UTF-8 and requires you to use `-Encoding utf8BOM` if you _want_ a BOM.
- If you're using Windows PowerShell and do _not_ want a UTF-8 BOM, use
$null =
New-Item
-Force ...
作为解决方案,并将修改后的字符串传递给-Value
参数。
因此:
$ThisFile = 'B:\Users\Desktop\onenote-new-entry.txt'
$data = Get-Content -Raw -Encoding utf8 $ThisFile
$data = $data.Replace('asdf','TESTREPLACE!')
# !! Note the caveat re BOM mentioned above.
$data | Set-Content -NoNewLine -Encoding utf8 $ThisFile
简化后的重新拟订,在一条管道内进行:
(Get-Content -Raw -Encoding utf8 $ThisFile) |
ForEach-Object Replace 'asdf', 'TESTREPLACE!' |
Set-Content -NoNewLine -Encoding utf8 $ThisFile
使用New-Item
解决方案时,如果输出文件必须没有BOM:
(Get-Content -Raw -Encoding utf8 $ThisFile) |
ForEach-Object Replace 'asdf', 'TESTREPLACE!' |
New-Item -Force $ThisFile |
Out-Null # suppress New-Item's output (a file-info object)
https://stackoverflow.com/questions/73790902
复制相似问题