使用批处理修改.properties文件中的字符串

时间:2018-11-15 12:28:36

标签: batch-file cmd insert

我试图通过执行脚本来修改csm.properties中的某个属性。 我仔细检查了一下,最后找到了这段代码。

set "search=CLASSPATH"
set "insert=CLASSPATH^=plugins^/Numbering.jar^\^:"

set "textFile="%workingPlace%bin\csm.properties""

FOR /f "delims=" %%i in ('type "%textFile%" ^& break ^> "%textFile%" ') do (
    FOR /f "tokens=1*delims==" %%g IN ("%%i") DO (
        IF /i "%%g" == %search% (
            set "line=%%i"
                setlocal enabledelayedexpansion
                >>"%textFile%" echo(!line:%search%=%insert%!
                endlocal
        )ELSE (
        %%i
        )
    )
)

此代码应读取文件中的每一行,并使用=作为分隔符。如果代码将“ CLASSPATH”作为属性,则应修改该行。 但似乎找不到CLASSPATH。

csm.properties的外观如下:

#Tue Jul 10 08:50:23 CEST 2018
JAVA_ARGS=-Xmx20000M -DLOCALCONFIG\=true -splash\:data/splash.png -Dmd.class.path\=$java.class.path -Dcom.nomagic.osgi.config.dir\=configuration -Desi.system.config\=data/application.conf -Dlogback.configurationFile\=data/logback.xml -Dsun.locale.formatasdefault\=true -Dinitial.user.language\=de
JAVA_HOME=jre1.8.0_152
BOOT_CLASSPATH=lib/xalan.jar
MAIN_CLASS=com.nomagic.osgi.launcher.ProductionFrameworkLauncher
MAC_JAVA_ARGS="-Xdock\:name\=Cameo Systems Modeler" -Xdock\:icon\=bin/md.icns -Dapple.laf.useScreenMenuBar\=true
APP_ARGS=
DEFAULT_MEMORY_SETTINGS_64=-Xmx[30%,1200,4000]M
DEFAULT_MEMORY_SETTINGS_32=-Xmx800M
CLASSPATH=lib/patch.jar\:lib/brand_api.jar
CONSOLE=false

修改后,CLASSPATH应如下所示:

CLASSPATH=plugins/Numbering.jar\:lib/patch.jar\:lib/brand_api.jar

4 个答案:

答案 0 :(得分:2)

更简单...

@echo OFF
setlocal

set "search=CLASSPATH"
set "insert=plugins/Numbering.jar\:"

set "textFile=%workingPlace%bin\csm.properties"

(FOR /f "usebackq tokens=1* delims==" %%i in ("%textFile%") do (
   if "%%i" equ "%search%" (
      echo %search%=%insert%%%j
   ) else if "%%j" neq "" (
      echo %%i=%%j
   ) else (
      echo %%i
   )
)) > temp.tmp

move /Y temp.tmp "%textFile%"

答案 1 :(得分:1)

您可以尝试一下:

@echo off
setlocal enableextensions disabledelayedexpansion

 set "replace=plugins^/Numbering.jar^\^:"
 set "textFile=%workingPlace%bin\csm.properties""

  for /f %%i in ('type "%textFile%" ^& break ^> "%textFile%" ') do (
     set "line=%%i"
     for /f "tokens=1* delims==" %%a in ("%%i") do (
     if "%%a"=="CLASSPATH" (
        setlocal enabledelayedexpansion
        >>"%textFile%" echo(!line!%replace%
        ) else (
        setlocal enabledelayedexpansion
        >>"%textFile%" echo(!line!
        endlocal
     )
  )
)

相似的理论,只有在第一个标记(%% i)匹配CLASSMAP时,它才会替换完整的字符串

请不要在set命令中更改双引号。

答案 2 :(得分:1)

这是我使用cmd.exe的内部命令( FINDSTR 除外)来完成此字符串替换任务的解决方案。

@echo off
setlocal EnableExtensions DisableDelayedExpansion

if not defined workingPlace set "workingPlace=%~dp0"
set "TextFile=%workingPlace%bin\csm.properties"
if not exist "%TextFile%" goto EndBatch

set "TempFile=%TEMP%\csm.properties.tmp"
set "FoundInfo="

(for /F delims^=^ eol^= %%I in ('%SystemRoot%\System32\findstr.exe /N "^" "%TextFile%"') do (
    set "Line=%%I"
    setlocal EnableDelayedExpansion
    set "Line=!Line:*:=!"
    if not defined FoundInfo (
        if defined Line (
            if /I "!Line:~0,10!" == "CLASSPATH=" (
                if /I "!Line!" == "CLASSPATH=" (
                    echo !Line!plugins/Numbering.jar
                    endlocal
                    set "FoundInfo=1"
                ) else if "!Line:plugins/Numbering.jar=!" == "!Line!" (
                    set "Line=!Line:~0,10!plugins/Numbering.jar\:!Line:~10!"
                    echo !Line!
                    endlocal
                    set "FoundInfo=1"
                ) else (
                    endlocal
                    goto DeleteTempFile
                )
            ) else (
                echo(!Line!
                endlocal
            )
        ) else (
            echo/
            endlocal
        )
    ) else (
        echo(!Line!
        endlocal
    )
))>"%TempFile%"

if not defined FoundInfo echo CLASSPATH=plugins/Numbering.jar>>"%TempFile%"
move /Y "%TempFile%" "%TextFile%"

:DeleteTempFile
if exist "%TempFile%" del "%TempFile%"

:EndBatch
endlocal

请阅读我对How to read and print contents of text file line by line?的回答,为什么仅使用命令 FINDSTR 输出文件csm.properties中的每一行,包括被 FOR 忽略的空行默认使用行号和:来避免 FOR 忽略任何行。行号和冒号通过命令行set "Line=!Line:*:=!"删除。

批处理文件顶部有未定义的环境变量FoundInfo,一旦 FOR的内部代码处理了以CLASSSPATH=开头的不区分大小写的行,便会设置该变量。 strong>循环。以CLASSSPATH=开头的行之后的文件中的每一行仅输出而无需进一步处理,包括空行。

CLASSSPATH=开始的行上方的空行也将以echo/输出,而无需任何进一步处理。

可以以三种不同的方式来处理以CLASSPATH=开头的不区分大小写的第一行:

  1. 该行仅包含CLASSPATH=
    在这种情况下,该行将输出为CLASSPATH=plugins/Numbering.jar,就是这样。
  2. 该行以CLASSPATH=开头,包含一个或多个字符,但字符串plugins/Numbering.jar不区分大小写。 在这种情况下,在plugins/Numbering.jar\:之后插入CLASSPATH=内输出该行。
    请注意,只有CLASSPATH=且有一个或多个尾随空格/制表符的行也将导致进入第二个分支,例如,输出CLASSPATH=plugins/Numbering.jar\: \:并在尾随空白处结束。
  3. 该行以CLASSPATH=开头,并且在该行的某个位置包含已经不区分大小写的字符串plugins/Numbering.jar
    在这种情况下, FOR 循环将立即跳转到标签DeleteTempFile,而不会处理捕获到的 FINDSTR 输出的任何行。因此,文件的最后修改日期不会更改,因为文件内容没有任何更改。 (我不希望对未真正修改的文件内容更改上次修改日期。)

FOR 循环之后,检查文件中是否根本没有以CLASSPATH=开头的行,不区分大小写。如果不是这种情况,则将CLASSPATH=plugins/Numbering.jar行添加到临时文件。

最后,临时文件肯定与csm.properties不同,如果可能的话,将临时文件移到现有文件csm.properties上,如果仍然存在,最后将临时文件删除。< / p>

注意1:如果文件csm.properties不包含空行或者可以接受在执行过程中删除空行,则无需使用 FINDSTR CLASSPATH=行的更新。

注释2:文件CLASSPATH=顶部带有csm.properties的行减少了处理时间。

此解决方案的功能概述:

  1. 在行中某处已经包含CLASSPATH=的{​​{1}}上,不修改文本文件。
  2. 仅当此行上还有其他类路径(或尾随空格)时,才在plugins/Numbering.jar之后插入plugins/Numbering.jar\:
  3. CLASSPATH=附加到不包含任何其他类路径的现有plugins/Numbering.jar行中(此行上没有尾随空格)。
  4. 如果文件至少存在,则将CLASSPATH=的整个CLASSPATH=行附加到plugins/Numbering.jar上,根本不包含该行。
  5. 保留文本文件中的空行,因此实际上只修改了CLASSPATH=开头的行。
  6. 请勿将带有VARIABLE==value(开头带有等号的值)的行修改为VARIABLE=value(删除开头有等号的行)。
  7. 不修改CLASSPATH=的拼写,因此也适用于文件中的classpath=ClassPath=
  8. 不删除以;开头的行,该行默认为 FOR 的行尾选项(eol)。

要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。

  • del /?
  • echo /?
  • endlocal /?
  • findstr /?
  • for /?
  • goto /?
  • if /?
  • move /?
  • set /?
  • setlocal /?

另请参阅Why is no string output with 'echo %var%' after using 'set var = text' on command line?How to set environment variables with spaces?这些答案解释了为什么在大多数情况下set variable="value"不好,以及与set "variable=value"有什么区别,后者是定义的首选语法具有字符串值的环境变量。

另请参阅Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files,它说明字符串比较如何与命令 IF 一起工作,以及为什么通常不应该将运算符EQUNEQ设计为整数比较的主要对象用于比较两个字符串,尽管这是可能的。在某些情况下,如果使用EQUNEQ进行字符串比较,在没有双引号的字符串的情况下,可能会导致意外的比较结果。

答案 3 :(得分:0)

@echo off
setlocal disabledelayedexpansion

set "search=CLASSPATH"
set "insert=plugins/Numbering.jar\:"

set "textFile=%workingPlace%bin\csm.properties"

for /f "usebackq delims=" %%i in ("%textFile%") do (
    for /f "tokens=1* delims==" %%g in ("%%i") do (
        if /i "%%g" == "%search%" (
            set "token1=%%g"
            set "token2=%%h"
            setlocal enabledelayedexpansion
            >> "%textFile%.tmp" echo(!search!=!insert!!token2!
            endlocal
        ) else (
            set "line=%%i"
            setlocal enabledelayedexpansion
            >> "%textFile%.tmp" echo(!line!
            endlocal
        )
    )
)

move "%textFile%" "%textFile%.bak" && move "%textFile%.tmp" "%textFile%"

似乎需要插入而不是替换。

for循环读取%textfile%的每一行和嵌套的for循环 在=上定界,以将令牌1和令牌2与其余部分一起存储。

如果找到%search%,则!token1!!token2!set 令牌值。 set通常可以在 这就是为什么要使用它。扩展延迟,所以毒物字符 被回显到文件而没有扩展到源文件中。

如果未找到%search%,则该行设置为!line!, 扩展被延迟,然后将行回显到文件。

注意: %workingPlace%未知,因此请根据需要更正路径。