解析XML對批處理非常痛苦。批處理不是一個好的文本處理器。但是,通過一定的努力,您通常可以從給定的XML文件中提取所需的數據。但輸入文件可以輕鬆地重新排列成一個等效的有效XML格式,這將破壞你的解析器。
隨着該聲明的出路......
這裏是一個天然的單批溶液
@echo off
setlocal disableDelayedExpansion
set input="test.xml"
set output="names.txt"
if exist %output% del %output%
for /f "delims=" %%A in ('findstr /n /c:"<con:testSuite name=" %input%') do (
set "ln=%%A"
setlocal enableDelayedExpansion
call :parseLine
endlocal
)
type %output%
exit /b
:parseLine
set "ln2=!ln:*<con:testSuite name=!"
if "!ln2!"=="!ln!" exit /b
for /f tokens^=2^ delims^=^" %%B in ("!ln2!") do (
setlocal disableDelayedExpansion
>>%output% echo(%%B
endlocal
)
set "ln=!ln2!"
goto :parseLine
的FINDSTR /N
選項只存在,以保證沒有行始於;
讓我們不必擔心煩人的默認FOR「EOL」選項。
打開和關閉延遲擴展的切換是爲了保護可能在輸入文件中的任何!
字符。如果您知道!
從不出現在輸入中,那麼您可以簡單地在頂部setlocal enableDelayedExpansion
並刪除所有其他setlocal
和endlocal
命令。
最後一個FOR/F使用特殊的轉義序列來將雙引號的規範定義爲DELIM字符。
回答附加問題的意見
你不能簡單地把額外的約束在現有的FINDSTR命令,因爲它會返回具有匹配的整條生產線。請記住,你自己說過,「在同一行」中可能有多個匹配字符串的實例。第一個名稱可能以正確的前綴開頭,同一行中的第二個名稱可能不會。你只想保留適當啓動的那個。
一種解決方案是簡單地改變echo(%%B >>%output%
線如下:
echo(%%B|findstr "^lp_" >>%output%
的FINDSTR使用正則表達式元字符^
以指定字符串必須以lp_
開始。此時引號已經被刪除,所以我們不必擔心它們。
但是,您可能會遇到將來必須在搜索字符串中包含"
的情況。另外,在初始FINDSTR中包含lp_
屏幕可能會稍微快一些,以免不必要地調用:parseLine
。
FINDSTR要求使用反斜槓轉義搜索字符串雙引號。但Windows CMD處理器也有自己的轉義規則。特殊字符如>
需要引用或轉義。原始代碼使用了引號,但是您希望在字符串中包含引號,並且會在您的命令中創建不平衡的引號。 Windows批處理通常成對使用引號。 CMD中至少有一個引號必須轉義爲^"
。如果報價需要爲CMD和FINDSTR轉義,那麼它看起來像\^"
。
但是,從CMD視角不再引用功能的字符串中的任何特殊字符也必須使用^
進行轉義。
下面是一個解決方案,可以轉義所有特殊字符。它看起來很糟糕,很混亂。
這裏是另一個解決方案,看起來好多了,但它仍然是混亂跟蹤什麼逃過CMD,什麼是逃過FINDSTR。
for /f "delims=" %%A in ('findstr /n /c:"<con:testSuite name=\"lp_^" %input%') do (
讓事情簡單一點的一種方法是將搜索轉換爲正則表達式。單個雙引號可以使用[\"\"]
進行搜索。這是一個匹配引用或引用的字符類表達式 - 我知道是愚蠢的。但它保持引號配對,以便CMD很高興。現在你不必擔心爲CMD轉義任何字符,你可以專注於正則表達式搜索字符串。
for /f "delims=" %%A in ('findstr /nr /c:"<con:testSuite name=[\"\"]lp_" %input%') do (
您的問題不使用正則表達式,所以我更改了問題標題以更好地匹配您的請求。 – dbenham