使用批处理文件查找并替换具有特殊字符的字符串



所以我在让这个批处理文件正常工作时遇到了一些问题。 我尝试了几种不同的方法来查找和替换字符串。

问题:我们必须经常更新数据库,这样做,文件会发生变化。 我必须将一个文件改回去才能正常工作。 这一行:

<network ipAdress="172.24.55.32" networkPort="9100" />

更改为此行:

<file filename="fffff" />

并且需要改回带有 IP 地址的第一行。

我尝试使用查找和替换子例程,并且可以让它在将"文件名"更改为"网络 ipAdress"的第一部分工作,但第二部分中的引号使脚本无法正常工作。 这是我拥有的代码。

@echo off
setlocal
call :FindReplace "file filename" "network ipAdress" BCPrint.XML
Timeout 2
call :FindReplace "fffff" "172.24.55.32" networkPort="9100" BCPrint.XML
exit /b
:FindReplace <findstr> <replstr> <file>
set tmp="%temp%tmp.txt"
If not exist %temp%_.vbs call :MakeReplace
for /f "tokens=*" %%a in ('dir "%3" /s /b /a-d /on') do (
for /f "usebackq" %%b in (`Findstr /mic:"%~1" "%%a"`) do (
echo(&Echo Replacing "%~1" with "%~2" in file %%~nxa
<%%a cscript //nologo %temp%_.vbs "%~1" "%~2">%tmp%
if exist %tmp% move /Y %tmp% "%%~dpnxa">nul
)
)
del %temp%_.vbs
exit /b
:MakeReplace
>%temp%_.vbs echo with Wscript
>>%temp%_.vbs echo set args=.arguments
>>%temp%_.vbs echo .StdOut.Write _
>>%temp%_.vbs echo Replace(.StdIn.ReadAll,args(0),args(1),1,-1,1)
>>%temp%_.vbs echo end with

我还尝试将第二部分设置为变量,例如:

set R2=172.24.55.32" networkPort="9100
call :FindReplace "file filename" "network ipAdress" BCPrint.XML
Timeout 2
call :FindReplace "fffff" "%R2%" BCPrint.XML

还有转义字符:

set ^R2=172.24.55.32" networkPort="9100^

我敢肯定,我尝试过几种不同的方法,我没有在不使用变量的情况下列出转义字符。 我已经走到了我能弄清楚的尽头。

有没有办法找到具有特殊字符的行并将其替换为具有特殊字符的行? 关于如何完成整行或带有引号和空格的第二部分的任何建议都很棒。 谢谢你的时间。

下载 JREPL.BAT 由Dave Benham编写,它是一个批处理文件/JScript 混合体,使用 JScript 对文件运行正则表达式替换,并将其存储在与下面的批处理文件相同的目录中。

@echo off
call "%~dp0jrepl.bat" "file filename=x22fffff" "network ipAdress=x22172.24.55.32x22 networkPort=x229100" /XSEQ /F BCPrint.XML /O -

x22"以十六进制形式指定,因为参数字符串不能包含双引号字符。

传递包含引号的参数非常困难,因为有几个地方可以识别这些字符,所以每次都必须建立单独的转义序列(^(。

以下示例脚本每次尝试call都会失败:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define argument here:
set "_ARG=R2=172.24.55.32" networkPort="9100"
setlocal EnableDelayedExpansion
rem // Echo argument string to prove that variable is set:
echo(!_ARG!
echo/
rem // Call sub-routine with delayed expansion:
call :SUB "!_ARG!"
endlocal
rem // Call sub-routine with normal (immediate) expansion:
call :SUB "%_ARG%"
rem // Call sub-routine with double normal expansion (`call`):
call :SUB "%%_ARG%%"
endlocal
exit /B

:SUB
setlocal DisableDelayedExpansion
rem // Delayed expansion disabled during argument expansion:
set "ARG=%~1"
setlocal EnableDelayedExpansion
rem // Delayed expansion enabled for argument display (`echo`):
echo(!ARG!
endlocal
endlocal
exit /B

避免此类问题的最简单方法是将变量名传递给子例程而不是其值:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define argument here:
set "_ARG=R2=172.24.55.32" networkPort="9100"
setlocal EnableDelayedExpansion
rem // Echo argument string to prove that variable is set:
echo(!_ARG!
echo/
endlocal
rem // Call sub-routine and pass variable name:
call :SUB _ARG
endlocal
exit /B

:SUB
setlocal EnableDelayedExpansion
set "#ARG=%~1"
rem /* Normal expansion is used to get the variable name;
rem    delayed expansion is used to read its value: */
echo(!%#ARG%!
endlocal
exit /B

若要更新包含"引号"的文件中的字符串,以下解决方案将起作用。

在与 bat 文件相同的目录中创建一个名为replace_quot.ps1的文件。 在此脚本中放置以下 2 行。

param([string]$Name_of_File)
(Get-Content $Name_of_File) -replace '&quot;', '"' | set-content $Name_of_File

在您的蝙蝠文件中输入以下行

set File_Name=File Name.txt
set "Find_String=<file filename="fffff" />"
set "Replace_String=<network ipAdress="172.24.55.32" networkPort="9100" />"
set "Find_String=%Find_String:"=&quot;%"
set "Replace_String=%Replace_String:"=&quot;%"
powershell -command "(Get-Content '%File_Name%') -replace '[x22]', '&quot;' | Set-Content '%File_Name%'"
powershell -command "(Get-Content '%File_Name%') -replace '%Find_String%', '%Replace_String%' | Set-Content '%File_Name%'"
Powershell.exe -executionpolicy remotesigned -File replace_quot.ps1 -Name_of_File "%File_Name%"

更新File_Name值以反映您的文件名。 bat 脚本将在字符串和文件中将引号替换为其十六进制值。接下来,它将找到需要替换的字符串并将其还原为所需的值。 最后,它将调用replace_quot.ps1脚本将文件的引号十六进制值更新为实际的引号字符。

最新更新