【问题标题】:Batch XML/CONF modify批量 XML/CONF 修改
【发布时间】:2022-08-14 20:32:15
【问题描述】:

大家下午好,我在尝试修改exe.conf文件中的两个值时遇到了很多困难,值是<add key=\"FileName\" value=\"20220623.txt\"/>,我需要修改value的值。

事实是,我对批处理语言不是很了解,但如果你能帮我一把,我将非常感激。

我试图用这条线和一些变体来做,但我无法修改它。

setlocal enableDelayedExpansion
set \"newValue=\'20221008.txt\'\"
type \"test.exe.conf\"|findstr  /v \"(<add key=\"row_process\" value=\"$!newValue!\"/>) >fileName.conf.new
move /y \"fileName.conf.new\" \"fileName.conf\"
  • 您发布的代码不是一行,而是几行。因此,我在应该在的地方添加了换行符。
  • 真的需要使用批处理文件,还是可以使用 Microsoft\'s PowerShell 代替?

标签: xml batch-file config script


【解决方案1】:

在 Windows 中,您可以使用来自 cscript.exe 的 MSXML 和 JavaScript

您将运行以下命令

cscript xmlbatch.wsf file.xml "new value"

这是一个用 JavaScript 编写的示例 xmlbatch.wsf 脚本。

<package>
<job id="t1">
<script language="JScript">

    var fso = new ActiveXObject( "Scripting.FileSystemObject" );
    var objArgs = WScript.Arguments;

    var strDOMObject = "MSXML2.FreeThreadedDOMDocument";
    var xml = new ActiveXObject( this.strDOMObject );
    
    if( objArgs.length < 2 ) {
        WScript.Echo( "Usage: cscript xmlbatch.wsf file.xml value");
        WScript.Echo( "Outputs the value(s) of all matching nodes" );
        WScript.Quit( 1 );
    }
    var strFileName = objArgs(0);
    var strValue = objArgs(1);

    var strXPath = "//add[@key='FileName']";

    if (fso.FileExists(strFileName) == false) {
        WScript.Echo( "Cannot locate " + strFileName );
        WScript.Quit( 1 );
    }

    try {
        if( !xml.load( strFileName ) ) {
            // output any errors, for invalid XML
            var strErrMsg = '';
            strErrMsg = xml.parseError.reason;
            if( xml.parseError.srcText != "" )
                strErrMsg += "Source: " + xml.parseError.srcText + "\r\n";
            if( xml.parseError.line != 0 )
                strErrMsg += "Line: " + xml.parseError.line + "\r\n";
            if( xml.parseError.linepos != 0 )
                strErrMsg += "Position: " + xml.parseError.linepos + "\r\n";
            throw new Error( xml.parseError.errorCode, strErrMsg ); 
        }

        var nodeList = xml.selectNodes( strXPath );
        if( nodeList != null ) {
            for( var i = 0; i < nodeList.length; i++ ) {
                nodeList[i].setAttribute( "value", strValue );
            }
            xml.save( strFileName );
        } else {
            WScript.Echo( "No matching nodes found in " + strFileName + " with XPath \"" + strXPath + "\"" );
            WScript.Quit( 1 );
        }
    
        WScript.Quit( 0 ); // success
    } catch( e) {
        WScript.Echo( e.description );
    }

</script> 
</job>
</package>

如果您的计算机还没有 MSXML,您可能需要安装它。

【讨论】:

  • 早上好!首先,非常感谢您的回答,也许我错过了提供有关我遇到的问题的更多信息,该数据“价值”是为了获取另一个文件夹中的日志,我正在制作一个蝙蝠,以便我可以指示我需要获取的日志(年/月/日),它本身就是保持文件完好无损,但只用我需要的日期修改该字段,因为稍后执行了一个调用该文件“exe.conf”的任务" 加上我想指明的日期。我希望我很清楚,如果没有,请告诉我。也谢谢你!
  • 您可以考虑计算新日期,并可能在 xmlbatch.wsf 中创建新文件夹。祝你的项目好运。
  • 使用具有适当 XML 解析工具的语言使这成为解决此问题的正确方法。
【解决方案2】:

在我看来,这是 SO 用语中的“XY”问题,即提出的问题是对未说明问题的错误解决方案。

基本问题似乎是:从包含行&lt;add key="FileName" value="20220623.txt"/&gt; 的模板文件test.exe.conf 开始,生成一个用新值替换20220623 的新文件。

OP 的代码旨在删除&lt;add key.. 行,并且该代码中没有任何内容可以进行替换。

因此,我将提出一个旨在治愈问题,而不是代码.

因为我对这个问题做了一些假设,所以它可能不是我们想要的。

第一个问题是用什么字符串代替22020623 - 我认为它可能会随着时间的推移而改变,所以我添加了几行来提供或输入该数据,而不是更改批处理文件。这意味着您可以执行此批次名称 20221008运行批处理并生成一个用20221008 替换22020623 的文件,或者执行此批次名称并且批处理将提示用字符串替换22020623。请注意,尽管在任何一种情况下输入的任何字符串都将被逐字替换。

第二个问题是我假设test.exe.conf 是一个模板文件,因此可以对其进行操作-因此,获取原始test.exe.conf 并对其进行修改,以便将每个&lt;add key... 行替换为唯一的字符串。我选择了substitute line here——但它几乎可以是任何字符串——例如@#123

@ECHO OFF
SETLOCAL
rem The following settings for the source directory, destination directory,
rem filename, and output filename are names
rem that I use for testing and deliberately include names which include spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.

SET "sourcedir=u:\your files"
SET "destdir=u:\your results"
SET "filename1=%sourcedir%\q73308290.txt"
SET "outfile=%destdir%\outfile.txt"

:: Get `newvalue`
SET "newvalue=%1"
IF NOT DEFINED newvalue SET /p "newvalue=New value ? "
IF NOT DEFINED newvalue GOTO :eof

(
FOR /f "usebackqdelims=" %%b IN ("%filename1%") DO (
 IF /i "%%b"=="substitute line here" (
  ECHO                     ^<add key="FileName" value="%newvalue%.txt"/^>
 ) ELSE ECHO %%b
)
)>"%outfile%"

GOTO :EOF

在应用于真实数据之前,请始终根据测试目录进行验证。

请注意,如果文件名不包含空格等分隔符,则usebackq%filename1% 周围的引号都可以省略。

显示的文件名适合我的系统,并允许我隔离问题的唯一数据。

该文件被逐行分配给%%b。如果%%b 不是触发线substitute line here 那么它只是由echo %%b 复制,但如果它一条触发线,然后生成所需的替代线。

来自echos 的所有输出都被收集到一个新文件outfile.txt 中,方法是用一对括号和&gt;filename 包围导致echoes 的代码。

--- cmets 后的修订

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION 
rem The following settings for the source directory, destination directory,
rem filename, and output filename are names
rem that I use for testing and deliberately include names which include spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.

SET "sourcedir=u:\your files"
SET "destdir=u:\your results"
SET "filename1=%sourcedir%\q73308290.txt"
SET "outfile=%destdir%\outfile.txt"

:: Get `newvalue`
SET "newvalue=%1"
IF NOT DEFINED newvalue SET /p "newvalue=New value ? "
IF NOT DEFINED newvalue GOTO :eof

FOR /f "tokens=5delims==/ " %%e IN ('FINDSTR /i /R /c:".*add key=\"FileName\" value=\"[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].txt\"/." "%filename1%"') DO SET "oldfn=%%~e"&GOTO process

:process
(
FOR /f "usebackqdelims=" %%b IN ("%filename1%") DO (
 ECHO "%%b"|FINDSTR /i /R /c:".*add key=\"FileName\" value=\"[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].txt\"/."  >nul
 IF ERRORLEVEL 1 (
  ECHO %%b
 ) ELSE (
  SET "line=%%b"
  echo !line:%oldfn%=%newvalue%.txt!
 )
)
)>"%outfile%"

:done
FC /w "%outfile%" "%filename1%"


GOTO :eof

在应用于真实数据之前,请始终根据测试目录进行验证。

请注意,如果文件名不包含空格等分隔符,则可以省略usebackq%filename1% 周围的引号。

这一次,%%e 从有问题的行中获取????????.txt 字符串并将其分配给oldfn

然后处理该文件,简单地重复不包含所需字符串的行,否则使用DELAYEDEXPANSION 替换旧文件名的新值

...尽管如果允许使用第 3 方实用程序,使用 SED 的解决方案可能会更干净。

【讨论】:

  • 早上好!首先,非常感谢您的回答,也许我错过了提供有关我遇到的问题的更多信息,该数据“价值”是为了获取另一个文件夹中的日志,我正在制作一个蝙蝠,以便我可以指示我需要获取的日志(年/月/日),它本身就是保持文件完好无损,但只用我需要的日期修改该字段,因为稍后执行了一个调用该文件“exe.conf”的任务" 加上我想指明的日期。我希望我很清楚,如果没有,请告诉我。也谢谢你!
【解决方案3】:

Batch 无法正式解析/编辑 XML,因此强烈建议使用像 这样的 XML 解析器。

xmlstarlet.exe ed -O -u "//add[@key='FileName']/@value" -v "20221008.txt" "fileName.conf"
<add key="FileName" value="20221008.txt"/>
xidel.exe -s "fileName.conf" -e "x:replace-nodes(//add[@key='FileName']/@value,function($x){attribute {name($x)} {'20221008.txt'}})" --output-node-format=xml
<add key="FileName" value="20221008.txt"/>

【讨论】:

    猜你喜欢
    • 2023-02-22
    • 2014-04-11
    • 2015-07-08
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多