使用批处理文件从一个行字符串中提取多个值

时间:2018-03-13 15:26:06

标签: batch-file cmd

我正在尝试从我已经从文件中提取的字符串中提取FileRef的每个值。不幸的是,字符串是一行,这使得使用for /f "tokens=*"更加困难。

字符串是:

"<Cim:TrnTable_list><Cim:TrnTable Id="Root"><Cim:TrnElem Ref="3" FileRef="A1-FS.elt"/><Cim:TrnElem Ref="4" FileRef="A1-MS.elt"/><Cim:TrnElem Ref="9" FileRef="Product\Product-v1\Product-v1-MD.elt"/><Cim:TrnElem Ref="11" FileRef="Product\Product-v2\Product-v2-MD.elt"/><Cim:TrnElem Ref="12" FileRef="RunnerPart_Assembly#1.elt"/></Cim:TrnTable></Cim:TrnTable_list>"

如何将FileRef的每个值插入到以下格式的变量中?:

A1-FS.elt?A1-MS.elt?Product\Product-v1\Product-v1-MD.elt?Product\Product-v2\Product-v2-MD.elt?RunnerPart_Assembly#1.elt

我的意思是,然后我可以使用for /f "delims=?"对吗?

或者有没有办法将上面示例中的每个?转换为一个字符串中的“新行”,或者甚至更好的方法来循环每个FileRef - 值?

非常感谢!

2 个答案:

答案 0 :(得分:3)

Squashman在他的comment中是正确的,使用能够原生处理XML数据的语言。

无论如何,如果你坚持使用纯Windows批处理脚本,你可以组装一个带有?符号的新字符串作为分隔符,如下面的脚本所示:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "_FILE=%~dpn0.txt" & rem // (path to file containing the line of text)
(set ^"_LF=^
%= empty line =%
^") & rem // (this constitutes a new-line character)

rem // Initialise collection variable:
set "COLL=?"
rem // Read line from file:
for /F "usebackq delims=" %%L in ("%_FILE%") do (
    set "LINE=%%~L"
    setlocal EnableDelayedExpansion
    rem // Replace `><` by `>` + line-break + `<`:
    set ^"LINE=!LINE:^>^<=^>^%_LF%%_LF%^<!^"
    rem // Read one tag enclosed within `<` and `>`:
    for /F "delims=" %%I in ("!LINE!") do (
        endlocal
        set "ITEM=%%I"
        rem // Extract string between ` FileRef` and `/>`:
        setlocal EnableDelayedExpansion
        set "ITEM=!ITEM:* FileRef=!"
        set "ITEM=!ITEM:/>=!"
        rem // Check for `=`-sign after `FileRef`:
        if "!ITEM:~,1!"=="=" (
            rem // Remove leading `=` and surrounding `""`:
            for /F "delims=| eol=|" %%F in ("!ITEM:~1!") do (
                endlocal
                set "NAME=%%~F"
                rem // Assemble return string using `?` as separator:
                setlocal EnableDelayedExpansion
                for /F "delims=| eol=|" %%J in ("!COLL!!NAME!?") do (
                    endlocal
                    set "COLL=%%J"
                    setlocal EnableDelayedExpansion
                )
            )
        )
    )
    endlocal
)
rem // Return collection variable:
setlocal EnableDelayedExpansion
echo(!COLL:~1,-1!
endlocal

endlocal
exit /B

切换delayed expansion是为了避免!符号出现问题。

比收集单个变量中的所有值更好的是在我看来只是循环遍历它们。

答案 1 :(得分:1)

这是暴力破坏的另一种方式。此代码将每个FileRef放入其自己的变量中,并对变量名称进行排序。

@echo off

FOR /F "delims=" %%G IN (line.txt) do set "line=%%G"

set i=0

:loop
set /a i+=1
set "line=%line:*FileRef=%"

FOR /F "tokens=1* delims==/" %%G IN ("%line%") DO (
    set "var%i%=%%~G"
    set "line=%%H"
)
echo "%line%"|find /I "fileref" >nul 2>&1 &&GOTO loop

set var
pause

执行时会输出。

C:\BatchFiles\SO\XML>bruteforce.bat
var1=A1-FS.elt
var2=A1-MS.elt
var3=Product\Product-v1\Product-v1-MD.elt
var4=Product\Product-v2\Product-v2-MD.elt
var5=RunnerPart_Assembly#1.elt
Press any key to continue . . .    

如果您不希望将数据分配到各自的变量中,则可以直接在%%G命令中使用FOR元变量。