批处理-从数组中删除元素 [英] Batch - Removing elements from an Array

查看:89
本文介绍了批处理-从数组中删除元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我相信答案很简单.我从一个地方获取一个目录列表,并将其存储到文本文档中.然后,我读取文本文档名称并将其存储到数组中.在此过程结束时,我希望擦除数组中的所有条目.

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

推荐答案

以下是我上面评论的内容,展示了使用setlocalendlocal来忘记变量的情况.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆