通过目录批量循环查找所有 XML 并将某个(未知)值替换为另一个(已知)值
Batch looping through directory find all XML and replace a certain (unknown) value with another (known) value
只是一个问题,我不知道这是否可能,但让我举例说明一下。
XML(包含几个值)
<WORKFLOW DESCRIPTION ="" ISENABLED ="YES" ISRUNNABLESERVICE ="NO" ISSERVICE ="NO" ISVALID ="YES" NAME ="DIMENSIONS" REUSABLE_SCHEDULER ="NO" SCHEDULERNAME ="Scheduler" SERVERNAME ="SERVER_NAME_DUMMY" SERVER_DOMAINNAME ="Domain_DUMMY" SUSPEND_ON_ERROR ="NO" TASKS_MUST_RUN_ON_SERVER ="NO" VERSIONNUMBER ="1">
我希望能够用 findstr 捕获(除非有更好的方法)SERVERNAME =(这在整个文档中只出现一次)并将其值替换为 SERVER_NAME_PROPER 以获得以下内容结果:
服务器名称="SERVER_NAME_PROPER".
问题是我不知道 SERVERNAME 的值,所以我不能严格搜索 SERVER_NAME_DUMMY(我也不知道长度,我看到了字符集对字符串的操作)。此外,这些行只是在它之后继续其他值和元素(没有结束行操作)。也许搜索 SERVERNAME =(promt value) 并在 SERVERDOMAIN_NAME 之前停止是明智的。因为该值在 SERVERNAME= "VALUE" 之后和 SERVERDOMAIN_NAME.
之前
我知道 SERVERNAME = 之后的值需要替换为我的硬编码值。如果我可以执行此操作,那么我可以批量创建一个 FOR 命令来循环整个目录中的所有文件并执行此特定命令。
我 2 天前在这里发布了一个替换脚本 。
查找字符串
"^(SERVERNAME=\x22^)^([a-z]+^)^(\x22^)"
替换为
WHATEVERYOUWANT
$1 是第一个括号,$2 第二个,$3 第三个。上面的插入符正在为 CMD 转义 - 解析后看起来像这样 (SERVERNAME=")([a-z]+)(")
无论何时使用 HTML 或 XML,最好将其解析为 HTML 或 XML,而不是试图将其抓取并破解为文本。这样,只要它是有效的标记,您就不会那么依赖格式。
为了使用 XML,您可以相当直观地将 Microsoft.XMLDOM
COM 对象与 Windows 脚本宿主一起使用(或者至少希望您可以遵循我下面演示中的逻辑) .这是混合批处理 + JScript 解决方案。用 .bat 扩展名和盐来保存它。
@if (@CodeSection == @Batch) @then
@echo off
setlocal
set "attribute=SERVERNAME"
set "new_value=This works."
for %%I in (*.xml) do (
rem // invoke JScript for each XML file
cscript /nologo /e:JScript "%~f0" "%%~I" "%attribute%" "%new_value%"
)
rem // end main runtime
goto :EOF
@end // end batch / begin JScript chimera
var DOM = WSH.CreateObject('Microsoft.XMLDOM'),
args = { file: WSH.Arguments(0), attr: WSH.Arguments(1), val: WSH.Arguments(2) };
DOM.load(args.file);
DOM.async = false;
DOM.setProperty('SelectionLanguage', 'XPath');
if (DOM.parseError.errorCode) {
WSH.Echo(DOM.parseError.reason);
WSH.Quit(1);
}
for (var d = DOM.selectNodes('//*[@' + args.attr + ']'), i = 0; i < d.length; i++)
d[i].setAttribute(args.attr, args.val);
DOM.save(args.file);
只是一个问题,我不知道这是否可能,但让我举例说明一下。
XML(包含几个值)
<WORKFLOW DESCRIPTION ="" ISENABLED ="YES" ISRUNNABLESERVICE ="NO" ISSERVICE ="NO" ISVALID ="YES" NAME ="DIMENSIONS" REUSABLE_SCHEDULER ="NO" SCHEDULERNAME ="Scheduler" SERVERNAME ="SERVER_NAME_DUMMY" SERVER_DOMAINNAME ="Domain_DUMMY" SUSPEND_ON_ERROR ="NO" TASKS_MUST_RUN_ON_SERVER ="NO" VERSIONNUMBER ="1">
我希望能够用 findstr 捕获(除非有更好的方法)SERVERNAME =(这在整个文档中只出现一次)并将其值替换为 SERVER_NAME_PROPER 以获得以下内容结果:
服务器名称="SERVER_NAME_PROPER".
问题是我不知道 SERVERNAME 的值,所以我不能严格搜索 SERVER_NAME_DUMMY(我也不知道长度,我看到了字符集对字符串的操作)。此外,这些行只是在它之后继续其他值和元素(没有结束行操作)。也许搜索 SERVERNAME =(promt value) 并在 SERVERDOMAIN_NAME 之前停止是明智的。因为该值在 SERVERNAME= "VALUE" 之后和 SERVERDOMAIN_NAME.
之前我知道 SERVERNAME = 之后的值需要替换为我的硬编码值。如果我可以执行此操作,那么我可以批量创建一个 FOR 命令来循环整个目录中的所有文件并执行此特定命令。
我 2 天前在这里发布了一个替换脚本
查找字符串
"^(SERVERNAME=\x22^)^([a-z]+^)^(\x22^)"
替换为
WHATEVERYOUWANT
$1 是第一个括号,$2 第二个,$3 第三个。上面的插入符正在为 CMD 转义 - 解析后看起来像这样 (SERVERNAME=")([a-z]+)(")
无论何时使用 HTML 或 XML,最好将其解析为 HTML 或 XML,而不是试图将其抓取并破解为文本。这样,只要它是有效的标记,您就不会那么依赖格式。
为了使用 XML,您可以相当直观地将 Microsoft.XMLDOM
COM 对象与 Windows 脚本宿主一起使用(或者至少希望您可以遵循我下面演示中的逻辑) .这是混合批处理 + JScript 解决方案。用 .bat 扩展名和盐来保存它。
@if (@CodeSection == @Batch) @then
@echo off
setlocal
set "attribute=SERVERNAME"
set "new_value=This works."
for %%I in (*.xml) do (
rem // invoke JScript for each XML file
cscript /nologo /e:JScript "%~f0" "%%~I" "%attribute%" "%new_value%"
)
rem // end main runtime
goto :EOF
@end // end batch / begin JScript chimera
var DOM = WSH.CreateObject('Microsoft.XMLDOM'),
args = { file: WSH.Arguments(0), attr: WSH.Arguments(1), val: WSH.Arguments(2) };
DOM.load(args.file);
DOM.async = false;
DOM.setProperty('SelectionLanguage', 'XPath');
if (DOM.parseError.errorCode) {
WSH.Echo(DOM.parseError.reason);
WSH.Quit(1);
}
for (var d = DOM.selectNodes('//*[@' + args.attr + ']'), i = 0; i < d.length; i++)
d[i].setAttribute(args.attr, args.val);
DOM.save(args.file);