Batch:不解析key-value的注释

Batch: Don't parse comment of key-value

我正在使用以下代码解析 config.ini 文件:

@setlocal enableextensions enabledelayedexpansion
@echo off
set file=%~1
set area=[%~2]
set key=%~3
set currarea=
for /f "usebackq delims=" %%a in ("!file!") do (
    set ln=%%a
    if "x!ln:~0,1!"=="x[" (
        set currarea=!ln!
    ) else (
        for /f "tokens=1,2 delims==" %%b in ("!ln!") do (
            set currkey=%%b
            set currval=%%c
            if "x!area!"=="x!currarea!" if "x!key!"=="x!currkey!" (
                echo !currval!
            )
        )
    )
)
endlocal

只要在键和值所在的同一行中没有注释,它就可以正常工作。

例如:

 [BACKUP]
 HOST=128.110.111.11   ;Comment is included in !currval!
 PORT=5901
 USER=user1

不幸的是,我找不到排除字符串“128.110.111.11”最后一个字符之后的所有内容的方法。

感谢任何帮助。谢谢!

实现目标的最佳批次是组合 for 循环来处理字符串。没有先天命令可以一步完成。

虽然在某种程度上,您可以通过将命令作为宏分配给变量来创建一个命令来完成必要的命令集

例如,在下面的脚本中,宏通过以下方式完成此目标的必要步骤:

  • 使用;
  • 分隔变量内容
  • 从头到尾遍历字符串的长度 - 该示例假定最大字符串长度为 250 个字符;示例点的任意数字。
  • 使用 If 条件逻辑和子字符串修改仅删除尾随空格
  • 停止进一步修改变量内容,方法是使用 true/false 开关标记字符串的最后一位包含 non-space 字符

注意:在宏扩展点使用子字符串修改来提供要处理的变量的名称。

@Echo off & Setlocal enableDelayedexpansion
 Set "RemTrail=Set "end=0"&(For /F "Tokens=1 Delims=;" %%G in ("^^!$v^^!")Do Set "$V=%%G")&For /L %%i in (250,-1,0)Do (if "^^!$V:~%%i,1^^!"==" " (If not "^^!End^^!"=="1" Set "$V=^^!$V:~0,%%i^^!")Else (If not "^^!$V:~%%i,1^^!"=="" Set "End=1"))"
rem // usage  example
 Set "string=trail of spaces    ; comment string  "
 Set "string2=uncommented string with trailing spaces and poison chars < &  " " | * >  "
Echo/[!string!]
Echo/[!string2!]
 %RemTrail:$V=String%
 %RemTrail:$V=String2%
Echo/[!string!]
Echo/[!string2!]

一个稍微修改的版本,允许在扩展时修改定界符,代价是 return 将修改后的结果放入固定的 return 变量($V)而不是原变量名:

@Echo off & Setlocal enableDelayedexpansion
 Set "RemTrail=For %%n in (1 2)Do if %%n==2 (Set "end=0"&(For /F "Tokens=1 Delims=DLM" %%G in ("^^!$V^^!")Do Set "$V=%%~G")&For /L %%i in (250,-1,0)Do (if "^^!$V:~%%i,1^^!"==" " (If not "^^!End^^!"=="1" Set "$V=^^!$V:~0,%%i^^!")Else (If not "^^!$V:~%%i,1^^!"=="" Set "End=1")))Else Set $V="
rem // usage  example
 Set "string=trail of spaces    ; comment string  "
 Set "string2=uncommented string with trailing spaces + poison chars < & | * " " >  "
Echo/[!string!]
Echo/[!string2!]
 %RemTrail:DLM=;%"!string!"
Echo/[!$V!]
 %RemTrail:DLM=;%"!string2!"
Echo/[!$V!]
 %RemTrail:DLM=+%"!string2!"
Echo/+ Delim example&Echo/[!$V!]

解决方案 1:

for /f "usebackq delims=;" %%a in ("!file!") do (

包括分号作为分隔符可确保仅将不包括分号的那部分行分配给 token 1,默认分配给元变量 %%a

缺点:字符串末尾和分号之间的 space 保留在 %%a 中,因此 currval 将被 echoed.

解决方案 2:

for /f "tokens=1,2 delims== " %%b in ("!ln!") do (

包含 space 作为额外的分隔符会将找到的第一个分隔符 (=) 和第二个分隔符 ([space]) 之间的值分配给 %%c.

缺点:显示为 %%c 的值将在 space

处被截断

解决方案 3:

使用解决方案1,然后更改

    set currval=%%c

    CALL :setcurrval %%c

然后 endlocal 变成

endlocal
goto :eof

:setcurrval
SET "currval=%*"
goto :eof

终止本地环境并退出批处理。
CALL 内部子程序 :setcurrval 将行的剩余部分的值分配给 currval,除了终端 spaces,因此产生 %%c 减去任何航站楼 spaces.

请注意冒号很重要。