XML の解析は、バッチでは非常に苦痛です。Batch は、そもそも適切なテキスト プロセッサではありません。ただし、ある程度の努力をすれば、通常は特定の 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オプションは、厄介なデフォルトの FOR "EOL" オプションについて心配する必要がないように/N
、a で始まる行がないことを保証するためだけに存在します。;
遅延展開のオンとオフの切り替えは!
、入力ファイルに含まれる可能性のある文字を保護するためです。が入力に表示されないことがわかっている場合は!
、単に上部にある他のコマンドとコマンドsetlocal enableDelayedExpansion
をすべて削除できます。setlocal
endlocal
最後の FOR /F は、特別なエスケープ シーケンスを使用して、二重引用符を DELIM 文字として指定できるようにします。
コメントの追加質問への回答
一致する行全体が返されるため、既存の FINDSTR コマンドに追加の制約を単純に追加することはできません。「同じ行に一致する文字列のインスタンスが複数ある可能性がある」と自分で言ったことを思い出してください。最初の名前は正しいプレフィックスで始まる場合があり、同じ行の 2 番目の名前はそうでない場合があります。適切に開始するものだけを保持する必要があります。
echo(%%B >>%output%
1 つの解決策は、次のように単純に行を変更することです。
echo(%%B|findstr "^lp_" >>%output%
FINDSTR は、正規表現のメタ文字を使用し^
て、文字列が で始まる必要があることを指定していますlp_
。引用符はこの時点で既に削除されているため、心配する必要はありません。
ただし、将来、"
検索文字列に含めなければならない状況に遭遇する可能性があります。lp_
さらに、不必要に呼び出されないように、最初の FINDSTR に画面を含める方がわずかに高速になる場合があります:parseLine
。
FINDSTR では、検索文字列の二重引用符をバック スラッシュでエスケープする必要があります。ただし、Windows CMD プロセッサにも独自のエスケープ規則があります。のような特殊文字は>
、引用符で囲むかエスケープする必要があります。元のコードでは引用符を使用していましたが、文字列に引用符を含める必要があるため、コマンドで引用符が不均衡になります。Windows バッチは通常、ペアの引用符が好きです。CMD の場合、少なくとも 1 つの引用符を としてエスケープする必要があります^"
。CMD と FINDSTR の両方で引用符をエスケープする必要がある場合は、次のようになり\^"
ます。
ただし、CMD の観点から機能的に引用されなくなった文字列内の特殊文字は、^
同様にエスケープする必要があります。
すべての特殊文字をエスケープする 1 つのソリューションを次に示します。それはひどく見え、非常に混乱しています。
for /f "delims=" %%A in ('findstr /n /c:^"^<con:testSuite^ name^=\^"lp_^" %input%') do (
はるかに優れた別のソリューションを次に示しますが、CMD でエスケープされたものと FINDSTR でエスケープされたものを追跡するのは依然として混乱を招きます。
for /f "delims=" %%A in ('findstr /n /c:"<con:testSuite name=\"lp_^" %input%') do (
物事を少し単純にする 1 つの方法は、検索を正規表現に変換することです。を使用して、単一の二重引用符を検索できます[\"\"]
。これは、引用符または引用符のいずれかに一致する文字クラス式です。ばかげています。ただし、CMDが満足できるように、引用符をペアに保ちます。これで、CMD の文字をエスケープすることを心配する必要がなくなり、正規表現検索文字列に集中できます。
for /f "delims=" %%A in ('findstr /nr /c:"<con:testSuite name=[\"\"]lp_" %input%') do (