批处理-从数组中删除元素 [英] Batch - Removing elements from an Array
问题描述
我相信答案很简单.我从一个地方获取一个目录列表,并将其存储到文本文档中.然后,我读取文本文档名称并将其存储到数组中.在此过程结束时,我希望擦除数组中的所有条目.
I believe that the answer to this should be pretty simple. I grab a list of dirs from a place and store them into a text document. I then read the text document names and store them into an array. At the end of this process I would like to have all the entries from the array wiped.
之所以要这样做,是因为我要遍历多个文件夹位置并将它们存储到同一阵列中.但是,当我每次都不清除数组时,当我稍后尝试将其打印出来时,似乎给了我各种各样的麻烦.
The reason I would like to do this, is because I am going to go though several folder locations and storing them into the same array. However when I don't clear the array each time it seems to give me all kinds of heck when I try to print it out later on down the line.
每次去填充下一个文件夹时,我都需要一个新的数组.
I need a fresh array each time I go to fill in the next folder.
REM **************************************************************************
REM this part needs to delete the value but doesnt
set !array[%arraywiper%]!=0
REM **************************************************************************
这是我遇到的问题的一个示例.可以运行下面的代码以查看我在说什么.
This is an example of the problem I am having. the code below can be ran to see what I am talking about.
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为我提供了一个很好的解决方案.这是它如何工作的一个例子.
Mr. Rojo has given me an excellent solution to this issue. This is an example of how it works.
@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
推荐答案
以下是我上面评论的内容,展示了使用setlocal
和endlocal
来忘记变量的情况.
Here's an illustration of what I commented above, demonstrating the use of setlocal
and endlocal
to forget variables.
@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
输出它们的值:
Or if you prefer to loop through the array elements rather than using set
to output their values:
@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]%
如果您必须使用索引数组式方法来操作变量的集合,我编写了一个:splice
函数,该函数的工作方式类似于JavaScript的
If you must manipulate the collection of variables with indexed array-ish methods, I wrote a :splice
function that works similarly to JavaScript's Array.prototype.splice()
. You can use this to remove elements, insert elements, a combination of both, and even to clear the entire array if you wish. (Just call :splice arrayname 0
to unset all elements from the array.)
@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
这篇关于批处理-从数组中删除元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!