读取包含特殊字符的文本文件并替换其中一个单词的批处理文件

3
我将尝试制作一个批处理文件,读取名为 "ayylmao.txt" 的文本文件,并查找特定单词 "hello" 并将其替换为 "xello"。
问题在于 "ayylmao.txt" 包含特定字符。
"Ayylmao.txt" 大致如下:
‹‹R‹Ę‹/M‹;Ču‹č˙˙˙‹‹@‰‹‹@CëC;Đu‹čq˙˙˙‹‹@C‹D$‰;7u®‹Ó‹Ćčúţ˙˙„Ŕu3Ŕ‰YZ]_^[ĂŤ@             SVWUÄđ‰$‹ô‹‰D$‹
‹‹@;Č‚†   ‹Ř‹>_‹ůz;ßrv;Ču!‹B‹A‹B‹)B‹x uV‹čđţ˙˙ëM‹Ř‹>_‹ůz;ßu
‹B‹)Bë3‹Z‰\$‹>‹‹.}+ű‰|$+Č‹‰HŤT$‹čMţ˙˙„Ŕu3 hello Ŕë°ë‹‹ ‰‹;D$…Y˙˙˙3ŔÄ]_^[ĂSVW‹Ú‹đţ   }ľ   ëĆ˙˙  ć  ˙˙‰sjh    Vj

你可以在最后一行看到“hello”这个单词。我希望批处理程序能够运行并生成一个名为ayylmao1.txt的文件,文件内容如下:
‹‹R‹Ę‹/M‹;Ču‹č˙˙˙‹‹@‰‹‹@CëC;Đu‹čq˙˙˙‹‹@C‹D$‰;7u®‹Ó‹Ćčúţ˙˙„Ŕu3Ŕ‰YZ]_^[ĂŤ@             SVWUÄđ‰$‹ô‹‰D$‹
‹‹@;Č‚†   ‹Ř‹>_‹ůz;ßrv;Ču!‹B‹A‹B‹)B‹x uV‹čđţ˙˙ëM‹Ř‹>_‹ůz;ßu
‹B‹)Bë3‹Z‰\$‹>‹‹.}+ű‰|$+Č‹‰HŤT$‹čMţ˙˙„Ŕu3 xello Ŕë°ë‹‹ ‰‹;D$…Y˙˙˙3ŔÄ]_^[ĂSVW‹Ú‹đţ   }ľ   ëĆ˙˙  ć  ˙˙‰sjh    Vj

你可以看到,"hello"现在变成了"xello"。
我发现了一个批处理文件,可以替换文本文件中的单词:
@echo off
REM -- Prepare the Command Processor --
SETLOCAL ENABLEEXTENSIONS
SETLOCAL DISABLEDELAYEDEXPANSION

if "%~1"=="" findstr "^::" "%~f0"&GOTO:EOF
for /f "tokens=1,* delims=]" %%A in ('"type %3|find /n /v """') do (
    set "line=%%B"
    if defined line (
        call set "line=echo.%%line:%~1=%~2%%"
        for /f "delims=" %%X in ('"echo."%%line%%""') do %%~X
    ) ELSE echo.
)

这段代码适用于没有特殊字符的文件,如果按照以下方式使用它,则效果非常好:
code.bat "hello" "xello" "ayylmao.txt">"ayylmao1.txt"

这段代码只输入了 ayylmao1.txt 中的一些特殊字符,但是替换了 hello。我希望所有特殊字符都能被输入。
我写成了这样:
chcp 1252
code.bat "hello" "xello" "ayylmao.txt">"ayylmao1.txt"

但是它没有起作用。它的效果就像第一段代码一样。

如果在PowerShell中有一种方法可以实现这个,我很乐意听取建议。

3个回答

5
你手头的文件看起来像是二进制文件,而不是文本文件,尽管其扩展名如此。使用批处理程序无法编辑二进制文件。在PowerShell中,这是可行的,但你需要使用数据字节而不是简单的文本进行操作。
以下是一个基本示例,它将查找文件中第一个出现的字符串“hello”,并将其替换为“xhello”:
$f = 'C:\path\to\ayylmao.txt'

$stext   = 'hello'
$rtext   = [char[]]'xhello'

$len    = $stext.Length
$offset = $len - 1

$data = [IO.File]::ReadAllBytes($f)

# find first occurrence of $stext in byte array
for ($i=0; $i -lt $data.Count - $offset; $i++) {
  $slice = $data[$i..($i+$offset)]
  if (-join [char[]]$slice -eq $stext) { break }
}

# Once you know the beginning ($i) and length ($len) of the array slice
# containing $stext you can "cut up" $data and concatenate the slices before
# and after $stext to the byte sequence you want to insert ($rtext):
#
#      |<--   $stext    -->|
# [...]['h','e','l','l','o'][...]  <-- $data
#    ^   ^               ^   ^
#    |   |               |   |
#    |   $i              |   $i+$len
#    $i-1                $i+$offset (== $i+$len-1)
#
$rdata = $data[0..($i-1)] + [byte[]]$rtext + $data[($i+$len)..($data.Count-1)]

[IO.File]::WriteAllBytes($f, $rdata)

如果您想让替换工作方式不同(也替换其他出现次数,替换不同的出现次数等),则需要调整此代码。


1

但它没有起作用。它的效果就像第一段代码一样。有帮助吗?

这个批处理代码来自于网站,并且有一个链接到讨论,解释为什么它不能处理特殊字符。


这对于像 OP 明显拥有的二进制文件无效。 - Ansgar Wiechers
@AnsgarWiechers 您是正确的。我将编码类型修改为Byte而不是UTF8。 - paul543
当编码设置为Byte时,您会得到一个字节数组,它没有Replace()方法。 - Ansgar Wiechers
@AnsgarWiechers 是的,你又是对的。哈哈。谢谢你的建议。我删除了我的PowerShell答案。我投票支持你的答案,所以它显示为最佳答案。我在我的答案中留下了关于第一个问题“为什么批处理文件不起作用”的网站链接。 - paul543
你可能想要总结一下论坛上的讨论,这样即使远程线程因某种原因消失,你的答案仍然是有效的(并且有帮助的)。 - Ansgar Wiechers
@AnsgarWiechers 是的,那是个好主意。我会仔细阅读讨论并总结一下为什么它不起作用。 - paul543

0

是的,PowerShell replace 命令可以替换字符串并保留特殊字符。要从批处理脚本中调用它,请使用以下行:

powershell -command "(get-content Ayylmao.txt) -replace 'hello','xello' | set-content Ayylmao.txt"

如果您想从命令行输入参数,则该行应为:
powershell -command "(get-content %3) -replace '%1','%2' | set-content %4"

如果你想使用批处理脚本中定义的变量,与任何批处理脚本一样

set file=Ayylmao.txt
set Search_criteria=hello
set Replace_criteria=xello
powershell -command "(get-content %file%) -replace '%Search_criteria%','%Replace_criteria%' | set-content %file%"

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