尝试将我在批处理文件中生成的字符串解析为 XML 文件的几个值

尝试将我在批处理文件中生成的字符串解析为 XML 文件的几个值

我正在尝试创建我的小批处理文件的 V2。我只知道批处理,所以如果可能的话,我更愿意这样做而不是使用 powershell,但如果必须这样做,我就必须这样做。

该应用程序只是将五个相同的文件复制到一个目录中。将子目录更改为我生成的唯一值,称为 CurrentDate。

现在他们问我是否可以在复制之前对文件进行唯一重命名,这应该很容易——我遇到的困难是这五个文件在 XML 文件中被引用。因此,为了实现这一点,我每次都需要编辑 XML 以使用新的唯一名称“%CurrentDate%.png”引用这五个文件

我已附上前后对比。幸运的是,源文件名在所有引用中都是相同的,并且从未改变过。“sample_”只有在每次运行时创建的目标文件上才需要是唯一的。

来源:

<?xml version="1.0" encoding="UTF-8"?>
< Id="sample_Back_-" Type="Value" Style="PRESET" Color="#FFFFFF" XOffset="0" YOffset="0">
    <Foundation FileName="sample_Back_--P.tif"/>
    <White FileName="sample_Back_--W.tif"/>
    <Color FileName="sample_Back_--CMYKRG.tif"/>
    <Preview FileName="sample_Back_-.png"/>
</end>

目的地:

<?xml version="1.0" encoding="UTF-8"?>
< Id="%SYSTEM_TIME%_Back_-" Type="Value" Style="PRESET" Color="#FFFFFF" XOffset="0" YOffset="0">
    <Foundation FileName="%CurrentDate%_Back_--P.tif"/>
    <White FileName="%CurrentDate%_Back_--W.tif"/>
    <Color FileName="%CurrentDate%_Back_--CMYKRG.tif"/>
    <Preview FileName="%CurrentDate%_Back_-.png"/>
</end>

如果相关的话,这是我生成 CurrentDate 的方法,只需几个 mkdir 和 robocopy 即可

for /F "tokens=1-4 delims=/ " %%A in ('date/t') do (
set DateDay=%%A
set DateMonth=%%B
set DateYear=%%C
)

for /F "tokens=1-4 delims=/ " %%D in ('time/t') do (
set DateTime=%%D
)

set CurrentDate=LOCATION-%DateDay%-%DateMonth%-%DateYear%-%time:~0,2%.%time:~3,2%

答案1

了解使用 bat 处理 .xml 文件是可能的,但它会涉及一些解释起来很复杂的事情,对于我糟糕的英语水平来说,请原谅我...我使用谷歌在线翻译,如果出现问题,请不要怪我:)

@echo off

cd /d "%~dp0"
set "_local=Rio_de_Janeiro_RJ"
setlocal EnableDelayedExpansion
2>nul del/q /f "%~dp0Q1615046.tmp" >nul

for /f %%i in ('wmic.exe OS Get localdatetime^|findstr \.')do set "_dt=%%~i"
     set "_dt=!_dt:~6,2!-!_dt:~4,2!-!_dt:~0,4!-!_dt:~8,2!.!_dt:~10,2!
    
for /f usebackq^tokens^=*^delims^= %%i in (`type "%~dp0Q1615046.xml"`)do set "_str=%%~i" && (
for %%i in ("<",">","!_dt!")do if not "%%~i"=="!_dt!" (cmd/v/s/c set "_srt=!_str:%%~i=^%%~i!"
     )else set "_str=!_str:sample=%_local%-%%~i!" & echo=!_str!>>"%~dp0Q1615046.tmp")
     
>nul move/y "%~dp0Q1615046.tmp" "%~dp0Q1615046.xml" && endlocal && goto :eof

  • 1.进入.xml文件所在文件夹,如果和bat一样,则使用cd /d "%~dp0",否则,用完整路径替换cd /d "Drive:\Full\Path\To\xml\Folder

  • 2.部分代码将使用双for循环,因此建议在运行时启用/使用扩展变量,使用Setlocal EnableDelayedExpansion

  • 3.使用不会因任何用户设置、地区和/或语言而改变输出的方法,以可预测和固定的布局获取日期/时间...

for /f %%i in ('wmic.exe OS Get localdatetime^|findstr \.')do set "_dt=%%~i"

set "_dt=!_dt:~0,4!-!_dt:~4,2!-!_dt:~6,2!-!_dt:~8,2!.!_dt:~10,2!"
rem ::       %%i: !_dt!       20210108095144.564000-180
rem ::  datetime: !_dt:~0,12! 20210108095144.564000-180
rem ::      year: !_dt:~0,4!  2021
rem ::     month: !_dt:~4,2!      01
rem ::       day: !_dt:~6,2!        08
rem ::      hour: !_dt:~8,2!          09
rem ::    minute: !_dt:~10,2!           51
  • 观察:使用命令wmic.exe OS Get localdatetime以固定且可预测的布局输出获取日期时间,其中没有用户更改,或语言/区域更改该输出,并添加findstr \.,过滤掉字面上 ( \) 带有 ( .) 个句点的行。
rem ::  porting to the layout intended in the question:
rem ::        day:      month:       year:       hour:     minute:
rem ::  !_dt:~6,2!  !_dt:~4,2!  !_dt:~0,4!  !_dt:~8,2! !_dt:~10,2!
rem ::          08         -01       -2021         -09         .51
  • 4.使用 bat 创建一个临时文件,在其中进行编辑,并在脚本结束时使用此临时文件覆盖原始 .xml
rem :: Delete if there is any previous execution already omitted possible non-existence error.
2>nul del/q /f "%~dp0Q1615046.tmp" >nul

....
rem :: Use the temporary file already containing the edits to overwrite the existing xml
>nul move/y "%~dp0Q1615046.tmp" "%~dp0Q1615046.xml"

5.使用for循环逐行列出已经在变量中定义行以供第二个循环使用的.xml 文件。

for /f usebackq^tokens^=*^delims^= %%i in (`type "%~dp0Q1615046.xml"`)do set "_str=%%~i" 

6.使用For /F循环逐行列出文件,your.xml已在变量中定义当前行以供第二行使用For /F环形。

for /f usebackq^tokens^=*^delims^= %%i in (`type "%~dp0Q1615046.xml"`)do set "_str=%%~i" 

7.您的额外/第二For /F循环将替换echo line命令,这是逐行完成的,

for %%i in ("<",">","!_dt!")do apply susbtrings replaces...

8.其中行包含<, >, sample将分别替换为^<;, ^>;, Rio_de_Janeiro_RJ-14-01-2021-05.51须遵守if() else() condition

...("<",">","!_dt!")do if not "%%~i"=="!_dt!" (cmd/v/s/c set "_srt=!_str:%%~i=^%%~i!"
     )else set "_str=!_str:sample=%_local%-%%~i!"

9.第一个循环逐行处理,第二个循环命令从该行开始发生<, 队伍的尽头>sample在线的中间,并设定一个if () else ()添加必要的转义符(在行首和行末,循环替换datatime(在该行的中间)最后出现的。

for /f (line by line) for /f (<, >, datetime_var) in actual line (
    if %%G not equal datetime_var add escaping ) else (
    this is last replace in line, so. echo variable line escapaded > fileTMP.xml)

观察:更换sample所需字符串仅会出现在sample字符串是否存在,当前行中是否没有当前结果,并立即执行此操作,最终的字符串以及必要的转义和替换将被回显到xml.tmp文件:

for /f usebackq^tokens^=*^delims^= %%i in (`type "%~dp0Q1615046.xml"`)do set "_str=%%~i" && (
for %%i in ("<",">","!_dt!")do if not "%%~i"=="!_dt!" (cmd/v/s/c set "_srt=!_str:%%~i=^%%~i!"
     )else set "_str=!_str:sample=%_local%-%%~i!" & echo=!_str!>>"%~dp0Q1615046.tmp")

10最后,在应用所有行和替换后,使用在执行中创建的临时文件覆盖原始 .xml 文件,方法是:move /y...

>nul移動/y"%~dp0Q1615046.tmp“”%〜dp0Q1615046.xml

相关内容