我正在尝试使用sfk.exe工具从xml中获取特定单词。它正在做的是获取整个单词/行所在的单词而不仅仅是该单词。我想获取该单词并将其存储在临时文件中,以便稍后存储在变量中。 这些词会改变,基本上是客户端的名称,它会根据客户端的xml而有所不同。
sfk find "C:\Env\Test\test.xml" "Name" > %temp%\Test.tmp
以上代码行提取以下内容:
<Org Updated="date" Owner="Test" Version="2/1/3/4"Database="Test" Client="Name">
所以基本上它让我全线,而我只想得到没有引号的“名字”。
答案 0 :(得分:1)
如果线条布局没有改变,那么你可以试试这个:
Set "Name=Microsoft"
For /F Tokens^=10^ Delims^=^" %%A in (
'Find /I "%Name%"^<"C:\Env\Test\test.xml"') Do Echo "%%A"
作为旁注,您是否要搜索Client=
,您可以进一步简化它:
For /F Tokens^=10^ Delims^=^" %%A in (
'sfk find "C:\Env\Test\test.xml" "Client="') Do Echo "%%A"
我已经使用了Find
和sfk
命令,它们可以根据您的需要进行互换。
答案 1 :(得分:1)
虽然批处理文件不是处理XML数据的最佳选择,因为它们本身不支持它们,但我想向您展示一种方法来执行您想要的操作:
@echo off
rem // Capture the output of the `find` command (`sfk` command is not necessary):
for /F "delims=" %%L in ('
^< "C:\Env\Test\test.xml" find /I " Client="
') do (
rem // Store found line in variable:
set "LINE=%%L"
setlocal EnableDelayedExpansion
rem /* Remove everything up to and including the first occurrence of ` Client`
rem from the string; then split off the leading `=` and the training `>`;
rem finally, remove the surrounding `""` from the remaining string: */
for /F "delims==>" %%I in ("!LINE:* Client=!") do (
endlocal
rem // Return the extracted string:
echo(%%~I
)
)
仅当每个适用行中出现 SPACE + Client
时,才会生效,后跟=
- 符号。此外,此Client=
属性必须是包含标记中的最后一个属性,因此整个属性定义Client="Name"
必须紧跟>
。
答案 2 :(得分:1)
虽然Windows批处理可能是一种蹩脚的处理xml
,但这个(非常简单)的情况可以使用(非常简单的)脚本解决,该脚本对解析的行的结构提供额外的初步假设。
然而,下面的解决方案强调(尽可能)通用方法,在包含标记内的Client=
属性的位置上没有前提,或者在一行内的其单一性(奇点)或前面的数量"
双引号等等:
@ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
for /F "delims=" %%G in ('
findstr /i /r "\<Client=" "D:\bat\SO\files\q44533501_input.xml"
') do (
rem ECHO=merely debugging output
ECHO %%G
set "_line=%%~G"
call :lineFound
)
goto :eof
:lineFound
rem remove cmd-poisonous characters `<` and `>` (replace them with spaces)
set "_line=%_line:<= %"
set "_line=%_line:>= %"
set "_takeNextItem="
rem parse
for %%g in ( %_line% ) do (
if defined _takeNextItem (
set "_takeNextItem="
set "_client=%%~g"
call :clientSet
) else (
if /I "%%~g" == "Client" set "_takeNextItem=%%~g"
)
)
goto :eof
:clientSet
rem ECHO=merely debugging output;
rem handle %_client% variable in desired manner instead
ECHO(%_client%
goto :eof
当然,您可以在第4行使用sfk find "C:\Env\Test\test.xml" "Client="
命令代替findstr /i /r "\<Client=" "D:\bat\SO\files\q44533501_input.xml"
。
示例输出(包括调试ECHO %%G
以显示输入xml
文件的可能变化):
==> D:\bat\SO\q44533501.bat
<Org Updated="date" Owner="Test" Version="2/1/3/4" Database="Test" Client="Name">
Name
<Org Updated="date" Database="Test" Client="Name2" Owner="Test" Version="2/1/3/4">
Name2
<Org Updated="yesterday" Client="Name3"></Org><Org Client="Name4" Updated="today">
Name3
Name4
==>
修改即可。要解释:lineFound
部分,让我们看看FOR
command(它主要用于处理文件,但您也可以处理文本字符串):
Conditionally perform a command on several files. Syntax FOR %%parameter IN (set) DO command Key set : A set of one or more files, separated by any standard delimiter. Wildcards can be used. command : The command to carry out, including any command-line parameters. %%parameter : A replaceable parameter: e.g. in a batch file use %%G (on the command line %G)
并利用我们要解析的xml
行只包含set
描述中上面提到的标准分隔符的事实,请参阅Delimiters:
分隔符将一个参数与下一个参数分开 - 它们分开了 命令行为单词。
参数通常用空格分隔,但任何一个都是空格 以下也是有效的分隔符:
- 逗号(,)
- 分号(;)
- 等于(=)
- Space()
- Tab()
一些示例可能会有所帮助:for %g in ( %_line% ) do …
循环过程,逐项,_line
变量在使用标准分隔符作为项目分隔符将其拆分后。原则上,我们获得一个序列,其中每个属性名称后跟属性值(但标记名称作为第一个项目):
==> for %g in ( %_line% ) do @echo %g
Org
Updated
"date"
Database
"Test"
Client
"Name2"
Owner
"Test"
Version
"2/1/3/4"
==>
请注意,对于此特定示例,_line
变量是硬编码的
==> set "_line=<Org Updated="date" Database="Test" Client="Name2" Owner="Test" Version="2/1/3/4">"
==> set "_line=%_line:<= %"
==> set "_line=%_line:>= %"
==> set _line
_line= Org Updated="date" Database="Test" Client="Name2" Owner="Test" Version="2/1/3/4"