2012-06-21 66 views
0

我有一個XML文件,我需要在XML文件中從如何使用Windows批處理

<con:testSuite name="testname" 

所有實例提取

testname 

提取特定的XML標記屬性的所有實例。

我不太清楚如何處理這個問題,或者這是否可以批量處理。

這是我迄今認爲:

1)使用FINDSTR和存儲每個具有

<con:testSuite name= 
在一個變量或臨時文件

行,像這樣:

FINDSTR /C:"<con:testSuite name=" file.xml > tests.txt 

2)以某種方式使用該文件或變量來提取字符串

請注意,有mi ght是同一行中匹配字符串的多個實例。

我是批處理新手,任何幫助表示讚賞。

+1

您的問題不使用正則表達式,所以我更改了問題標題以更好地匹配您的請求。 – dbenham

回答

3

解析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並刪除所有其他setlocalendlocal命令。

最後一個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 (
+0

謝謝。我試過了,它似乎工作。我怎樣才能得到只有那些以某種模式開始的名字?例如,我只需要以lp_開頭的測試名(例如lp_test1,lp_test2等)。我嘗試在findtr命令中包含「lp_部分,但我不確定如何轉義雙引號。」 「 謝謝 –

+1

@AndresDelaBarra - 查看我更新的答案。如果答案符合您的需求,請不要忘記接受答案(點擊複選標記)。它讓其他人知道這個問題已經回答了,它會給你2分以接受答案,並且給予提供答案的人15分。 – dbenham