前言
我是批处理新手,已经做了大约 2 周。当我向它添加特定的 for 循环时,我的函数没有遵循我认为正常的程序流程规则。删除 for 循环后,函数遵循我期望的程序流程,但输出仍然不是我想要的。根本问题是延迟扩展变量中的延迟扩展变量。
我已经多次检查了括号,在靠近底部的完整代码中我找不到任何关于它们的不平衡之处。程序流程明智,这没有任何意义,添加 for 循环会影响 for 循环之前的语句。我唯一能想到的是发生了一些奇怪的错误,代码根本没有执行完整的循环并在循环之后立即到达我的暂停语句。
我实际上正在尝试做的事情
我正在尝试用 ; 分隔单行字符串 在我想稍后分隔的字符串中使用未知/可变数量的标记和其他可能的分隔符(如逗号)。这不能通过批处理预先制作的 for 循环来完成,FOR / F 只能同时执行行和/或设置标记数以及常规 for 循环由分号和逗号分隔。我想先用分号分隔,然后再用逗号分隔。为此,我试图用标签制作自己的简单分割线。我遇到了一个涉及延迟扩展我的变量的问题。这里的例子:
不是完整的代码,而是延迟扩展问题的代码
setlocal EnableDelayedExpansion
set "TestArgument=%~1"
set /a "CurrentIndex=0"
set /a "DelimIndex=0"
set /a "LoopCount=0"
:ForEach
IF "!TestArgument:~%CurrentIndex%,1!"=="" (goto :ForEachEnd & echo End of list)
echo testing semicolon
IF NOT "!TestArgument:~%CurrentIndex%,1!"==";" (SET /a CurrentIndex=%CurrentIndex%+1 & goto :ForEach & echo found non ;) ELSE (
set /a "LengthToSearch=%CurrentIndex%-%DelimIndex%"
SET "currentArg=!TestArgument:~%DelimIndex%,!LengthToSearch!!
我想从函数的这个特定部分得到什么
示例输入:
set "ICMPv4RuleTest="Enable Echo Ping Request ICMPv4;Protocol,ICMPv4;Enabled,Yes;LocalIP,Any;RemoteIP,Any;Direction,In;Action,Allow""
期望的输出示例:一个 For 循环(上面的标签),其中每次迭代都采用一个由 ; 分隔的字符串。所以第一次迭代会Enable Echo Ping Request ICMPv4
取值。上面的重点是获取输入并以某种方式对其进行子串化,以便每次迭代都由分号分隔
上面的代码,特别是最后一行导致了问题,因为(我认为)程序将其读取为延迟扩展!TestArgument:~%DelimIndex%,!
(这会出错)然后!(这没什么)只留下 LengthToSearch 作为原始字符串。我想要的是在子字符串操作之前扩展 LengthToSearch 值,然后扩展/运行/执行子字符串操作的扩展并将其设置为 CurrentArg(由 ; 分隔的单行字符串)。我不能将 % 符号与 LengthtoSearch 一起使用,因为它似乎与子字符串操作在同一范围内,但是我可以将 % 符号与 DelimIndex 一起使用(因为那超出了范围?我不知道)。
我试过的
我尝试了子字符串行(最后一行)的变体,包括:
SET "currentArg=!TestArgument:~%DelimIndex%,%LengthToSearch%!
什么都不打印。SET "currentArg=!TestArgument:~%DelimIndex%,!!LengthToSearch!!!
打印 31(DelimIndex 的文字参数)。SET "currentArg=%TestArgument:~%DelimIndex%,!!LengthToSearch!!%
什么都不打印。SET "currentArg=%TestArgument:~%DelimIndex%,!LengthToSearch!%
什么都不打印。
我已经尝试了其他一些,但它们肯定是不对的。我认为应该是这样的
SET "currentArg=!TestArgument:~%DelimIndex%,!LengthToSearch!!
.
方式,但这只是有上述问题。我在这里做了一些研究,发现其他人的字符串搜索和替换问题与我的问题相似,他们使用 FOR 循环将延迟扩展值插入到延迟扩展子字符串操作中作为 for 循环参数。我想我可以使用相同的方法,所以我尝试了这个(对最后一行有很大的改变):
setlocal EnableDelayedExpansion
set "TestArgument=%~1"
set /a "CurrentIndex=0"
set /a "DelimIndex=0"
set /a "LoopCount=0"
:ForEach
IF "!TestArgument:~%CurrentIndex%,1!"=="" (goto :ForEachEnd & echo End of list)
echo testing semicolon
IF NOT "!TestArgument:~%CurrentIndex%,1!"==";" (SET /a CurrentIndex=%CurrentIndex%+1 & goto :ForEach & echo found non ;) ELSE (
set /a "LengthToSearch=%CurrentIndex%-%DelimIndex%"
FOR /F "tokens=*" %%A IN ("!LengthToSearch!") DO (SET "currentArg=!TestArgument:~%DelimIndex%,%%A!)
那就是事情变得非常奇怪的时候。出于某种原因,添加 forloop 会导致整个 ELSE 案例无法执行。当我运行我的代码时,
IF NOT "!TestArgument:~%CurrentIndex%,1!"==";"
只“运行”一次(它并没有真正运行它应该运行的所有内容),然后循环就真的中断了。我并不是说它走到了循环的末尾,它只是完全忽略了整个函数的其余部分。我在此处的完整代码中多次检查了括号:
完整的功能代码
:FirewallRuleTestFunc
echo got to function
setlocal EnableDelayedExpansion
set "TestArgument=%~1"
ECHO PARAM WAS "%~1"
echo TestArgument was "%TestArgument%"
set /a "CurrentIndex=0"
set /a "DelimIndex=0"
set /a "LoopCount=0"
echo trying foreach
:ForEach
echo got to foreach
IF "!TestArgument:~%CurrentIndex%,1!"=="" (goto :ForEachEnd & echo End of list)
echo testing semicolon
IF NOT "!TestArgument:~%CurrentIndex%,1!"==";" (SET /a CurrentIndex=%CurrentIndex%+1 & goto :ForEach & echo found non ;) ELSE (
echo WHY IS THIS NOT BEING REACHED.
echo CurrentIndex is %CurrentIndex%
echo startposition was first: %DelimIndex%
set /a "LengthToSearch=%CurrentIndex%-%DelimIndex%"
echo length to search was: !LengthToSearch!
echo length to search was: %LengthToSearch%
echo startposition was: %DelimIndex%
FOR /F "tokens=*" %%A IN ("!LengthToSearch!") DO (SET "currentArg=!TestArgument:~%DelimIndex%,%%A!)
echo loop of ; Arg was: !currentArg!
set /a DelimIndex=!CurrentIndex!
echo Delim index was: %DelimIndex%
IF !LoopCount! NEQ 0 (
echo afterfirstloop
FOR /F "tokens=1,2 delims=," %%A IN ('netsh advfirewall firewall show rule name^="!RuleName!" ^| FIND "%%A"') DO (
echo loop of , A was '%%A'
SET "FoundArgument=%%B"
SET "FirewallRuleExists=%%A"
IF "!FirewallRuleExists!"=="" (echo TEST FAILED firewall rule with name "!RuleName!" NOT FOUND)
IF "!FoundArgument!"=="Yes" (echo Test Passed) ELSE (echo Test Failed was "!FoundArgument!")
)
) ELSE (SET "RuleName=!currentArg!" & set /a "LoopCount=%LoopCount%+1" & echo firstloop done)
echo got past if else
)
:ForEachEnd
echo end of THING
endlocal
echo SOMETHING
goto:EOF
并且第二个 IF ( ) 的 ELSE 情况下的IF NOT "!TestArgument:~%CurrentIndex%,1!"==";"
任何回声,以及第二个 IF 之前的任何其他回声都不会真正发生。这对我来说绝对没有意义,我无法理解为什么在添加 for 循环时它会忽略程序流,而在注释掉 for 循环时程序流可以工作。我想要做的就是有一个 for 循环,每个我可以指定的分隔符循环一次。我唯一的猜测是发生了一些错误,导致它直接进入 EOF。在我的函数被调用之后会有一个暂停,因为我的程序的其余部分应该是无关紧要的。而我目前正在研究这一部分。该函数的输入如下所示:
函数调用示例:
set "ICMPv4RuleTest="Enable Echo Ping Request ICMPv4;Protocol,ICMPv4;Enabled,Yes;LocalIP,Any;RemoteIP,Any;Direction,In;Action,Allow""
call :FirewallRuleTestFunc %ICMPv4RuleTest%
我非常沮丧,我只需要一些帮助。我会继续尝试各种事情,但这是我需要完成的程序的最后一部分,我只想获得稳定、有效和高效的东西,而不必做我以前做过的事情,使用行列和幻数来检查通过令牌设置防火墙。(我正在测试一个脚本来配置一些设置,以便可以设置公司网络)。