我相信这个答案应该很简单。我从一个地方获取目录列表并将它们存储到文本文档中。然后我读取文本文档名称并将它们存储到一个数组中。在这个过程结束时,我希望擦除阵列中的所有条目。
我想这样做的原因是因为我要去几个文件夹位置并将它们存储到同一个数组中。然而,当我尝试在以后打印出来的时候,每当它似乎给我各种各样的麻烦时,我都不清理阵列。
每次我填写下一个文件夹时,我都需要一个新的数组。
REM **************************************************************************
REM this part needs to delete the value but doesnt
set !array[%arraywiper%]!=0
REM **************************************************************************
这是我遇到的问题的一个例子。可以运行下面的代码来查看我在说什么。
ECHO OFF & setLocal EnableDELAYedExpansion
cls
REM creates folder for text doc
IF EXIST "c:\TEMP" (echo.) else (md c:\TEMP\)
REM Scans C:\Program Files (x86) and stores into a text doc
(for /f "delims=" %%a in ('dir /a:D-H-S /on /b "C:\Program Files (x86)"') do echo %%a)> c:\TEMP\dork_array_wipe.txt
REM Counts the folders in the text doc
for /d %%a in ("C:\Program Files (x86)\"*) do (
set /a locationcount+=1
)
REM Stores the values from the doc into an array
for /F "usebackq delims=" %%a in ("c:\TEMP\dork_array_wipe.txt") do (
set /A i+=1
call set array[%%i%%]=%%a
)
set arraywiper=1
:Arraywipeloop19
IF %arraywiper%==%locationcount% GOTO Arraywipecomplete19 else (
REM Prints array to show value entered array
echo array (%arraywiper%): !array[%arraywiper%]!
REM **************************************************************************
REM this part needs to delete the value but doesnt
set !array[%arraywiper%]!=0
REM **************************************************************************
Set /a arraywiper+=1
REM Prints out array in question to veryify change took place
echo array (%arraywiper%): !array[%arraywiper%]!
GOTO Arraywipeloop19
)
:Arraywipecomplete19
pause
先生。 Rojo给了我一个很好的解决方案。这是它如何运作的一个例子。
@echo off
setlocal
set "array[0]=foo"
set "array[1]=bar"
set "array[2]=baz"
set "array[3]=qux"
set "array[4]=quux"
set "array[5]=corge"
echo.
echo first printout
echo %array[0]%, %array[1]%, %array[2]%, %array[3]%, %array[4]%, %array[5]%
pause
rem // starting with element 3, delete 2 elements and insert 3 new
call :splice array 3 2 grault garply waldo
echo.
echo second printout
echo %array[0]%, %array[1]%, %array[2]%, %array[3]%, %array[4]%, %array[5]%, %array[6]%, %array[7]%
pause
call :splice array 0
REM set array[
REM goto :EOF
echo.
echo third printout
echo %array[0]%, %array[1]%, %array[2]%, %array[3]%, %array[4]%, %array[5]%, %array[6]%
pause
set "array[0]=foo"
set "array[1]=bar"
set "array[2]=baz"
set "array[3]=qux"
set "array[4]=quux"
set "array[5]=corge"
echo.
echo fourth printout
echo %array[0]%, %array[1]%, %array[2]%, %array[3]%, %array[4]%, %array[5]%, %array[6]%
pause
:splice <array_name> <startIDX> [<deleteCount> [<item1> [<item2> [...]]]]
rem // works like JavaScript Array.prototype.splice()
rem // https://developer.mozilla.org/en-US/search?q=Array.prototype.splice()
setlocal enabledelayedexpansion
set /a idx = 0, argskip = 0, inserted = 0, orig_ubound = -1
if "%~3"=="" (set /a "resume = 1 << 30") else set /a resume = %~2 + %~3
for /f "tokens=1* delims==" %%I in ('set %~1[') do (
set /a orig_ubound += 1
if !idx! lss %~2 (
set "tmp[!idx!]=%%J"
set /a ubound = idx, idx += 1
) else (
if !inserted! equ 0 (
for %%# in (%*) do (
set /a argskip += 1, inserted = 1
if !argskip! gtr 3 (
set "tmp[!idx!]=%%~#"
set /a ubound = idx, idx += 1, resume += 1
)
)
)
if !idx! geq !resume! (
set "tmp[!idx!]=%%J"
set /a ubound = idx, idx += 1
) else set /a resume -= 1
)
)
set "r=endlocal"
for /f "tokens=1* delims=[" %%I in ('2^>NUL set tmp[') do (
set "r=!r!&set "%~1[%%J""
)
for /L %%I in (%idx%,1,%orig_ubound%) do set "r=!r!&set "%~1[%%I]=""
%r%&exit/b
答案 0 :(得分:3)
以下是我在上面评论的内容的说明,演示了使用setlocal
和endlocal
来忘记变量。
@echo off
setlocal
set idx=0
rem // populate array
setlocal enabledelayedexpansion
for /f "delims=" %%I in ('dir /b /a:-d') do (
set "array[!idx!]=%%~nxI"
set /a idx += 1
)
rem // display array
set array[
rem // destroy array
endlocal
rem // result
set array[
或者如果您更喜欢循环遍历数组元素而不是使用set
来输出它们的值:
@echo off
setlocal
set idx=0
rem // populate array
setlocal enabledelayedexpansion
for /f "delims=" %%I in ('dir /b /a:-d') do (
set "array[!idx!]=%%~nxI"
set /a ubound = idx, idx += 1
)
rem // display array
for /L %%I in (0,1,%ubound%) do echo array[%%I]: !array[%%I]!
rem // destroy array
endlocal
rem // result
echo %array[0]%
编辑:如果您必须使用索引的array-ish方法操作变量集合,我编写了一个与JavaScript Array.prototype.splice()
类似的:splice
函数。您可以使用它来删除元素,插入元素,两者的组合,甚至可以根据需要清除整个数组。 (只需call :splice arrayname 0
取消设置数组中的所有元素。)
@echo off
setlocal
set "array[0]=foo"
set "array[1]=bar"
set "array[2]=baz"
set "array[3]=qux"
set "array[4]=quux"
set "array[5]=corge"
rem // starting with element 3, delete 2 elements and insert 3 new
call :splice array 3 2 grault garply waldo
set array[
goto :EOF
:splice <array_name> <startIDX> [<deleteCount> [<item1> [<item2> [...]]]]
rem // works like JavaScript Array.prototype.splice()
rem // https://developer.mozilla.org/en-US/search?q=Array.prototype.splice()
setlocal enabledelayedexpansion
set /a idx = 0, argskip = 0, inserted = 0, orig_ubound = -1
if "%~3"=="" (set /a "resume = 1 << 30") else set /a resume = %~2 + %~3
for /f "tokens=1* delims==" %%I in ('set %~1[') do (
set /a orig_ubound += 1
if !idx! lss %~2 (
set "tmp[!idx!]=%%J"
set /a ubound = idx, idx += 1
) else (
if !inserted! equ 0 (
for %%# in (%*) do (
set /a argskip += 1, inserted = 1
if !argskip! gtr 3 (
set "tmp[!idx!]=%%~#"
set /a ubound = idx, idx += 1, resume += 1
)
)
)
if !idx! geq !resume! (
set "tmp[!idx!]=%%J"
set /a ubound = idx, idx += 1
) else set /a resume -= 1
)
)
set "r=endlocal"
for /f "tokens=1* delims=[" %%I in ('2^>NUL set tmp[') do (
set "r=!r!&set "%~1[%%J""
)
for /L %%I in (%idx%,1,%orig_ubound%) do set "r=!r!&set "%~1[%%I]=""
%r%&exit/b
答案 1 :(得分:1)
批处理数组也可以通过列表与索引变量结合使用,以将元素与索引值进行匹配
下面使用宏演示了如何对列表类型的数组进行仿真:
每个宏通过以下组合接受Args:
子字符串修改
{e}
变量名和array
变量名替换array clone / return
For循环If else构造
使用宏和列表(而不是被调用的函数)或将大量值分配给关联的变量可以大大加快执行速度。
Splice宏包含一种验证方法
@Echo off
rem /* Macro Definition - Arg order mandatory in each macro. */
(Set \n=^^^
%= Newline var for macro definitions. Do Not Modify =%
)
::: Reserved Variable names used for Macro's:
::: \n Splice Extract Remove Groupname Insert Prepend Append Rvar RV cArr
::: {i} {i#} Tokens
rem /* Usage: %Splice:{e}={ListVarName}{Insertion Index}{OPTIONAL-NewListVarname}% */
Set Splice=For %%n in (1 2)do if %%n==2 (%\n%
For /F "Tokens=1,2,3 Delims={}" %%1 in ("{e}") Do (%\n%
Set "Groupname=%%1"%\n%
Set "{i#}=%%2"%\n%
Set "cArr=%%3"%\n%
)%\n%
Set "Prepend="%\n%
Set "Append="%\n%
Set "{i}=0"%\n%
For %%G in (!Groupname!)Do For %%E in (!%%G!)Do (%\n%
If !{i}! LSS !{i#}! (%\n%
If "!Prepend!" == "" (Set "Prepend=%%E")Else (Set "Prepend=!Prepend! %%E")%\n%
)%\n%
If !{i}! GEQ !{i#}! (%\n%
If "!Append!" == "" (Set "Append=%%E")Else (Set "Append=!Append! %%E")%\n%
)%\n%
Set /A "{i}+=1"%\n%
)%\n%
If Not "!cArr!" == "" (Set "!cArr!=!Prepend! !Insert! !Append!")Else (Set "!Groupname!=!Prepend! !Insert! !Append!")%\n%
)Else Set Insert=
rem /* Usage: %Remove:{e}={ListVarName}{OPTIONAL-NewListVarname}% Index/es to be removed as Integer list */
Set Remove=For %%n in (1 2)do if %%n==2 (%\n%
For /F "Tokens=1,2 Delims={}" %%1 in ("{e}") Do (%\n%
Set "Groupname=%%1"%\n%
Set "cArr=%%2"%\n%
Set "Rvar="%\n%
)%\n%
Set "Prepend="%\n%
Set "Append="%\n%
Set "{i}=0"%\n%
For %%G in (!Groupname!)Do For %%E in (!%%G!)Do (%\n%
Set /A "{i}+=1"%\n%
Set "{i#}=1"%\n%
For %%t in (!Tokens!)Do If %%t EQU !{i}! Set "{i#}=0"%\n%
If !{i#}! EQU 1 (%\n%
If "!Rvar!" == "" (Set "Rvar=%%E")Else (Set "Rvar=!Rvar! %%E")%\n%
)%\n%
)%\n%
If Not "!cArr!" == "" (Set "!cArr!=!Rvar!")Else (Set "!Groupname!=!Rvar!")%\n%
)Else Set Tokens=
rem /* Usage: %Extract:{e}={ListVarName}{OPTIONAL-ReturnVarName[Default - RV ]}%Index/es to be extracted as Integer list */
Set Extract=For %%n in (1 2)Do if %%n==2 (%\n%
For /F "Tokens=1,2 Delims={}" %%1 in ("{e}") Do (%\n%
Set "Groupname=%%1"%\n%
Set "Rvar=%%2"%\n%
If "!Rvar!" == "" ( Set "Rvar=RV" )%\n%
)%\n%
Set "{i}=0"%\n%
Set "!Rvar!="%\n%
For %%G in (!Groupname!)Do For %%E in (!%%G!)Do (%\n%
Set /A "{i}+=1"%\n%
For %%v in (!{i#}!)Do If !{i}! EQU %%v (%\n%
For %%r in (!Rvar!)Do If "!%%r!" == "" ( Set "!Rvar!=%%E" )Else ( Set "!Rvar!=!%%r! %%E" )%\n%
)%\n%
)%\n%
)Else Set {i#}=
rem /* Delayed Expansion Must be enabled to expand macro's */ ::: EXAMPLE USAGES:
Setlocal EnableDelayedExpansion
Set List=1 2 3 4 5 6 7 8
Set list
Echo/rem /* insert new elements. Example = insert "9 9" after the 3rd element. */
%Splice:{e}={List}{3}%9 9
Set List
Echo/rem /* extract element/s. example = 1st 4th and 6th elements */
%Extract:{e}={List}{YourReturnVar}%1 4 6
Set YourReturnVar
Echo/rem /* remove elements from list. example=remove the 1st 4th and 6th elements */
%Remove:{e}={List}%1 4 6
Set List
Echo/rem /* Clone existing list; inserting elements . Example = insert previously extracted elements
Echo/rem at the max index [ from the last {i} index returned ] */
%Splice:{e}={List}{!{i}!}{clone}%!YourReturnVar!
Set Clone
示例输出:
答案 2 :(得分:0)
我无法添加注释,但应提及以下对上述答案的限制......
当您在设置数组的行中的代码中远程使用set array[ & endlocal
时,除非在被调用函数内使用endlocal,否则它可能还会擦除与之前设置的数组变量无关的所有其他变量,其中唯一的变量set是属于数组的那个。如果该限制为真,则应在答案中提及。
这引起了人们的担忧,是否可以在一个代码周围普遍使用ENDLOCAL来擦除目标变量,以及上述方法是否通用。