我编写了以下批处理脚本,它接受input.xml,修改它,将新文件输出到temp.xml,然后将temp.xml复制到input.xml。
它对我来说很好,但有时它会将一个空的temp.xml文件复制到input.xml,这会导致我丢失数据。
以下是代码:
@echo off
setlocal EnableDelayedExpansion
set dt=%date:~7,2%-%date:~4,2%-%date:~10,4%_%time:~0,2%-%time:~3,2%-%time:~6,2%
cd C:\test\inputFiles
(for /F "delims=" %%a in ('findstr /I /L "<initialTransferReference>" input.xml') do (
set "line=%%a"
set "line=!line:*<initialTransferReference>=!"
for /F "delims=<" %%b in ("!line!") do (
set a=%%b
)))
set /a newvalue=a+1
(for /F "delims=" %%a in (input.xml) do (
set "line=%%a"
set "newLine=!line:initialTransferReference>=!"
if "!newLine!" neq "!line!" (set "newLine=<initialTransferReference>%newvalue%</initialTransferReference>"
)
echo !newLine!
)) > temp.xml
copy /y temp.xml input.xml
del temp.xml
copy /y input.xml "C:\test\modifiedFile\input_%dt%.xml"
为什么脚本有时会将空的temp.xml文件复制到input.xml?
答案 0 :(得分:0)
JosefZ可能在他的评论中是正确的 - 如果input.xml被另一个进程锁定,您的文件将被空的temp.xml覆盖。但是锁定必须是临时的,否则COPY命令也会失败,原来将保持不变。
我能想到的另一个潜在原因是,如果你的input.xml在进程开始时已经是空的。但是空的input.xml应该是预期的结果。
以下最小的更改将阻止锁定问题。我保留了尽可能多的代码,除了我重新格式化间距和换行符以更好地显示所有这些括号的逻辑。
我在第二个循环周围放了一组额外的括号,只有在内循环成功时才有条件地移动和复制文件。否则我删除临时文件,原始文件保持不变,并且不会创建日期副本。我还使用MOVE代替COPY,然后使用DEL。
请注意,如果无法读取任何行,则2ND FOR / F循环也会返回失败,因此如果input.xml开始为空,则不会创建过时的副本。但是如果找不到<initialTransferReference>
行,则不会进行任何更改,但仍会创建过时的副本。
@echo off
setlocal EnableDelayedExpansion
set dt=%date:~7,2%-%date:~4,2%-%date:~10,4%_%time:~0,2%-%time:~3,2%-%time:~6,2%
cd C:\test\inputFiles
(
for /F "delims=" %%a in ('findstr /I /L "<initialTransferReference>" input.xml') do (
set "line=%%a"
set "line=!line:*<initialTransferReference>=!"
for /F "delims=<" %%b in ("!line!") do (
set a=%%b
)
)
)
set /a newvalue=a+1
(
(
for /F "delims=" %%a in (input.xml) do (
set "line=%%a"
set "newLine=!line:initialTransferReference>=!"
if "!newLine!" neq "!line!" (
set "newLine=<initialTransferReference>%newvalue%</initialTransferReference>"
)
echo !newLine!
)
) > temp.xml
) && (
move /y temp.xml input.xml >nul
copy /y input.xml "C:\test\modifiedFile\input_%dt%.xml" >nul
) || del temp.xml 2>nul
您的代码可以大大简化。例如,您可以轻松地在一个循环中完成所有操作。
此外,您的代码高度依赖于XML的格式。如果<initialTransferReference>
行上有多个标记,或者标记分为多行,则会失败。如果文件包含!
,它也将失败。
一个更强大的解决方案可以用批量编写,但我不会打扰 - 它很快变成一个复杂的,神秘的混乱。
我建议您使用我的JREPL.BAT正则表达式文本处理器:-)
JREPL.BAT是纯脚本(混合JScript /批处理),可以在XP之后的任何Windows机器上本机运行。解决方案可以简单:
@echo off
setlocal
set dt=%date:~7,2%-%date:~4,2%-%date:~10,4%_%time:~0,2%-%time:~3,2%-%
call jrepl "\d+(?=\s*</initialTransferReference>)" "Number($0)+1" /j /m /f "C:\test\inputFiles\input.xml" /o - && copy /y "C:\test\inputFiles\input.xml" "C:\test\modifiedFile\input_%dt%.xml"
以上查找结束标记之前的数字,并将其替换为递增的值。如果线路上还有其他标签,它并不在乎。它甚至允许值和结束标记位于不同的行上。
只有在JREPL成功修改input.xml时才会创建日期副本。如果input.xml被锁定,或者由于在</initialTransferReference>
之前未找到整数值而未进行任何更改,则不会创建它。
与大多数正则表达式XML&#34;解决方案&#34;一样,仍然可以在其上抛出可能失败的有效XML,但您可能不得不竭尽全力使其失败。它很可能适用于您投入的任何现实世界数据。
如果您真的想要一个强大的解决方案,那么您应该使用VBS,JScript或PowerShell来正确地解析和操作XML。
我不喜欢您如何获取时间戳值,因为它取决于您的语言环境使用的日期和时间格式。但这是一个完全不同的话题。
回复评论中的问题的最新更新
您可以再使用一个JREPL而不是XCOPY将日期字符串附加到Filename标记,并在一个步骤中写入输出文件。请注意我使用行继续来使代码更容易阅读。
@echo off
setlocal
set dt=%date:~7,2%-%date:~4,2%-%date:~10,4%_%time:~0,2%-%time:~3,2%-%
call jrepl "\d+(?=\s*</initialTransferReference>)" "Number($0)+1" /j /m /f "C:\test\inputFiles\input.xml" /o - && ^
call jrepl "(?=\s*</FileName>)" "_%dt%" /m /f "C:\test\inputFiles\input.xml" /o "C:\test\modifiedFile\input_%dt%.xml"
答案 1 :(得分:0)
for /F "delims=" %%a in (input.xml) do ( ...
文件, errorlevel 1
将无法提升The system cannot find the file input.xml
并显示input.xml
消息。
将great dbenham's answer和lukk's answer合并到如果给定文件或目录被锁定,如何检入命令行问题:代码中嵌入的检查循环如下。无人值守timeout
...
@echo off
setlocal EnableDelayedExpansion
set dt=%date:~7,2%-%date:~4,2%-%date:~10,4%_%time:~0,2%-%time:~3,2%-%time:~6,2%
pushd C:\test\inputFiles
:locktest
set "_locktest="
((call )>>"temp.xml" ) 2>nul || set "_locktest=locked"
If defined _locktest (
echo file is locked; unlock it, please
rem pause instead of timeout in the next line?
timeout /T 5 >NUL 2>&1
goto :locktest
)
::::::::::::::::::::::::::::::::::
:: your script remainder here ::
::::::::::::::::::::::::::::::::::