我需要解决以下批处理文件中的问题,
用户在每个下一个输入元素之间都有一个空格。
输入需要作为数组元素存储在数组中。
输入必须作为案例名称,并且需要执行特定的案例。因此,需要执行具有数组元素名称的每一种情况。
数组大小不是预先确定的。由于用户可以提供任意数量的输入,所以它是不同的。
算法需要像这样,
用户输入号为1 2 4 6,它们存储在数组ai中。
a[i] = {1,2,4,6}
for i = 1 to len(a[i])
CALL :CASE_%a[i]% # jump to :CASE_1, :CASE_2, etc.
:CASE_1
Echo “am in case1”
:: go to the for loop
:CASE_2
Echo “am in case2”
:: go to the for loop
:CASE_3
Echo “am in case3”
:: go to the for loop
:CASE_4
Echo “am in case4”
:: go to the for loop
:CASE_5
Echo “am in case5”
:: go to the for loop
:CASE_6
Echo “am in case6”
:: go to the for loop
:CASE_7
Echo “am in case7”
:: go to the for loop
:CASE_8
Echo “am in case8”
:: go to the for loop
End for当输入为1 2 4 6时,只需执行Case_1、Case_2、Case_4、Case_6 .
这在批处理文件中可能吗?
发布于 2014-01-16 12:23:05
我将把这个问题分成三部分。将数据放入数组中,从数组中获取数据,并模拟case指令,而不是批处理。
@echo off
setlocal enableextensions enabledelayedexpansion
set /p "data=Input data:"让我们假设用户只输入数字值(以避免所有必要的检查,只查看问题),如所示,空格是分开的。把它们放到一个“数组”里。不,数组不存在于批处理脚本中,但是可以模拟给变量指定正确的名称。
set "arrayLength=0"
for %%e in (%data%) do (
set /a "arrayLength+=1"
set "a[!arrayLength!]=%%e"
)这将对输入数据进行迭代,对于每个元素,将增加一个计数器,并创建一个名为a[+counter value+]的变量。不,它不是数组,只是一个具有名称的变量,它允许我们模拟数组正弦。当计数器(arrayLength)在循环中发生变化时,需要延迟扩展才能读取这个更改的值,而变量读取从%var%到!var!的变化则需要进行sintax。
现在,数据在“数组”中。我们将遍历“数组”,检查其内容。
for /l %%i in (1 1 %arrayLength%) do (
echo element %%i is : !a[%%i]!
)读取每个元素内容的新税也需要延迟扩展。在这种情况下,我们不会改变块内的值,但是在每次迭代中,读取变量的名称都会被生成。请记住,没有数组,只有一个附属名的变量。我们使用for变量生成名称。
如何测试“数组”的值?
echo Test IF
for /l %%i in (1 1 %arrayLength%) do (
if "!a[%%i]!"=="1" (
echo Case 1
) else if "!a[%%i]!"=="2" (
echo Case 2
) else if "!a[%%i]!"=="3" (
echo Case 3
) else if "!a[%%i]!"=="4" (
echo Case 4
) else if "!a[%%i]!"=="5" (
echo Case 5
) else if "!a[%%i]!"=="6" (
echo Case 6
) else (
echo NO CASE
)
)这会在“数组”上迭代,并使用级联的IF sintax来检查允许的值。编写代码很容易,速度快,但如果情况经常发生更改,维护起来就不太舒服了。
IF级联的一个替代方法是使用子程序。根据“数组”元素的值,调用一个标签或另一个标签。只要准确地命名标签就行了。
然后您可以测试标签/子例程是否存在,然后调用它。
或者,您可以直接调用它,而不需要在调用中检查和测试将指示标签不存在的错误。
或者可以定义一个例程表。
对于示例,如果定义了下列标签
:case[1]
echo Case 1
goto :eof
:case[2]
echo Case 2
goto :eof
:case[3]
echo Case 3
goto :eof
:case[4]
echo Case 4
goto :eof
:case[5]
echo Case 5
goto :eof
:case[6]
echo Case 6
goto :eof使用以前在批处理文件中检查是否存在(%~f0是当前具有完整路径的批处理文件)来调用此子程序的代码可以是
rem Use labels in batch with previous test of existence
for /l %%i in (1 1 %arrayLength%) do (
findstr /l /c:":case[!a[%%i]!]" "%~f0" > nul 2>nul
if not errorlevel 1 (
call :case[!a[%%i]!]
) else (
echo NO CASE
)
)这使用findstr读取当前的批处理文件,搜索:case[n]标签。在没有错误的情况下,已经找到标签并进行了调用。但是,必须读取批处理文件来测试标签是否存在并不是最快的操作。
若要不检查标签是否存在并直接执行调用,可以使用以下代码
rem Use labels in batch without check
for /l %%i in (1 1 %arrayLength%) do (
ver>nul
call :case[!a[%%i]!] 2>nul
if errorlevel 1 echo NO CASE
)'ver>nul`行对称地确保在调用子例程之前清除错误级别。发出调用并检查错误级别。但是无法知道错误级别是来自调用指令还是来自被调用子例程的内部。
另一个选项是有一个rutines表来调用数组中元素的每个可定位值。因此,如果为每个允许的元素创建了一个表,则指向子程序的标签。
set "func[1]=:case[1]"
set "func[2]=:case[2]"
set "func[3]=:case[3]"
set "func[4]=:case[4]"
set "func[5]=:case[5]"
set "func[6]=:case[6]"下面的代码可以调用相应的子例程,检查是否定义了该值的函数
for /l %%i in (1 1 %arrayLength%) do (
for %%v in (!a[%%i]!) do if defined func[%%v] (
call !func[%%v]!
) else (
echo NO CASE
)
)内部for需要获得对“数组”中的值的引用,该值用于访问func“数组”中函数的名称。
还有..。任何人都能想到的更好的东西。
在这之后,应该使用哪一种代码?什么对你有用。这完全取决于真正要解决的问题。
IF级联是快速和容易的,但对于频繁变化的情况下,更难以维护。
查找是费时的。
没有支票的电话可能是一个真正的梦魇。
函数表位于中间。它的速度不如在块中包含所有代码的速度要快于IF解决方案中的代码,但是在检查子例程定义时比findstr更快。编写代码并不难,但对于小问题来说,这是不必要的。
对于简单的情况,IF构造是您所需要的。对于复杂的问题,如果代码很长,并且需要更改情况,那么.函数表使事情变得更简单。
所以,它会导致
@echo off
setlocal enableextensions enabledelayedexpansion
set /p "data=Input data:"
set "arrayLength=0"
for %%e in (%data%) do (
set /a "arrayLength+=1"
set "a[!arrayLength!]=%%e"
)
rem func[ allowedValue ] = label to call
set "func[1]=:handleCase_1"
set "func[2]=:handleCase_2"
set "func[3]=:handleCase_3"
set "func[4]=:handleCase_4"
set "func[5]=:handleCase_5"
set "func[6]=:handleCase_6"
for /l %%i in (1 1 %arrayLength%) do (
for %%v in (!a[%%i]!) do if defined func[%%v] (
call !func[%%v]!
) else (
echo NO CASE
)
)
for /l %%i in (1 1 %arrayLength%) do (
if "!a[%%i]!"=="1" (
echo Case 1
rem Or, we can
rem call :handleCase_1
) else if "!a[%%i]!"=="2" (
echo Case 2
) else if "!a[%%i]!"=="3" (
echo Case 3
) else if "!a[%%i]!"=="4" (
echo Case 4
) else if "!a[%%i]!"=="5" (
echo Case 5
) else if "!a[%%i]!"=="6" (
echo Case 6
) else (
echo NO CASE
)
)
endlocal
exit /b
:handleCase_1
echo Case 1
goto :eof
:handleCase_2
echo Case 2
goto :eof
:handleCase_3
echo Case 3
goto :eof
:handleCase_4
echo Case 4
goto :eof
:handleCase_5
echo Case 5
goto :eof
:handleCase_6
echo Case 6
goto :eof发布于 2014-01-16 12:19:34
Windows批处理对数组没有真正的支持,但是可以通过巧妙地使用变量名来模拟它们。例如,a[1]和a.len是普通变量名,脚本不知道任何名为a的对象。我倾向于用点符号代替:a.1,a.2,. a.len。你可以自由地发展你自己的风格。
@echo off
setlocal enableDelayedExpansion
set a[1]=1
set a[2]=2
set a[3]=4
set a[4]=6
set a.len=4
:: You can also do multiple numerical assignments on one line using SET /A
:: set /a "a[1]=1, a[2]=2, a[3]=4, a[4]=6, a.len=4"
for /l %%i in (1 1 %a.len%) do (
call :CASE_!a[%%i]!
)
:: You must exit the script so you don't fall into the subroutines after the loop finishes
exit /b
:CASE_1
Echo am in case1
exit /b
:CASE_2
Echo am in case2
exit /b
:CASE_3
Echo am in case3
exit /b
:CASE_4
Echo am in case4
exit /b
:CASE_5
Echo am in case5
exit /b
:CASE_6
Echo am in case6
exit /b
:CASE_7
Echo am in case7
exit /b
:CASE_8
Echo am in case8
exit /b发布于 2014-01-16 20:43:52
我回顾了您的问题,在我看来,它不需要使用数组。我想你是在说一份清单。这样,就可以通过这样一种方式来解决所述问题:
@echo off
rem The user gives the input with a space in between every next input element.
set /P input=
rem The input has to be taken as the case name and the particular case need to be executed.
rem Hence every case with the name of the array element need to be executed.
for %%i in (%input%) do call :CASE_%%i
goto :EOF
:CASE_1
Echo am in case1
exit /B
:CASE_2
Echo am in case2
exit /B
:CASE_3
Echo am in case3
exit /B
:CASE_4
Echo am in case4
exit /B
:CASE_5
Echo am in case5
exit /B
:CASE_6
Echo am in case6
exit /B例如:
C:\> test
1 2 4 6
am in case1
am in case2
am in case4
am in case6任何被迫使用不必要数组的解决方案都会更加复杂.
https://stackoverflow.com/questions/21159536
复制相似问题