Batch array scripts, to make life easier

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
T3RRY
Posts: 58
Joined: 06 May 2020 10:14

Batch array scripts, to make life easier

#1 Post by T3RRY » 04 Sep 2020 12:11

I often see questions on stackoverflow about defining "arrays" with batch. Here's a little something I whipped that I can use whenever I want to establish an array without having to code specifically for it.

The usage info and Error checking for is reasonably thorough making it simple to use

The script can be used to define, clear, append or modify array contents, including the value of array sub elements. It accepts parameters as args And / Or from files (Only one file's contents may be appended to the array at a time.)

Code: Select all

@Echo off
 Set "Usage=Echo/###&Echo/Call %~n0 "/A:Group Name" "element" "element..."&Echo/Call %~n0 "/A:Group Name" "/F:Filepath.ext"&Echo/Call %~n0 "/A:Group Name" REM : Clears the Array for the given Group Name&Echo/Call %~n0 "/A:Group Name" "element" "element..." "/O:3" REM : Overides Elements from the index supplied&Exit /B 1"
 Set "UseErr=Echo/&Echo/Usage Error - Ensure command extensions and Delayed Expansion are enabled with: &Echo/Setlocal EnableExtensions EnableDelayedExpansion&Echo/ or from the command line:&Echo/CMD /V:On /K&Exit /B 1"
 If Not "!Comspec!"=="%Comspec%" (%UseErr%)
 (Set "SwParam="&Set "SwFParam="&Set "#ORP#=0"&Set "#FP#=0"&Set "Inset="&Set "#STDOut=0"&Set "GRPNm="&Set "!GRPNm!="&Set "SubEl="&Set "FlNm=%~n0") > Nul 2> Nul
 If "%~1"=="" (%Usage:###=!FlNm! Usage:%) Else Call :GetArgs %*
 If Errorlevel 1 Exit /B 1
 If "!GRPNm!"=="" %Usage:###=/A:Groupname required%
 If "!#ORP#!"=="1" Echo/!SwParam!|findstr /RX [0-9]* > Nul 2> Nul
 If not "!SwParam!"=="" If Errorlevel 1 (%Usage:###=O:!SwParam! #Arg invalid. Only Integers accepted.%)
 If "!#ORP#!"=="1" Set "#!GRPNm!=0"
 If "!#%GRPNm%!"=="" Set "#!GRPNm!=0"
 If "%#FP#%"=="1" (
  If exist "!SwFParam!" (
   For /F "Delims=" %%G in (!SwFParam!)Do If Not "%%~G"=="" (
    For %%x in ("!GRPNm![!#%GRPNm%!]")Do (
     Setlocal DisableDelayedExpansion
     If "%#STDOut%"=="1" Echo/%%~x=%%~G
     Endlocal & Set "%%~x=%%G"
    )
    Set /A "#!GRPNm!+=1" > Nul
   )
  ) Else (%Usage:###=/F:!SwFParam! Invalid path%)
 )
 If not "!Inset!"=="" (
  For %%G in (!Inset!)Do (
   For %%x in ("%GRPNm%[!#%GRPNm%!]")Do (
    Setlocal DisableDelayedExpansion
    If "%#STDOut%"=="1" Echo/%%~x=%%~G
    Endlocal & Set "%%~x=%%~G"
   )
   If Not "!SubEL!"=="" Set "%%~G=!SubEl!"
   Set /A "#!GRPNm!+=1" > Nul
  )
 ) Else (
  If Not "%#FP#%"=="1" (
   For /F "Tokens=1,2 Delims==" %%I in ('Set %GRPNm%')Do Set "%%~I=" > Nul 2> Nul
   Set "#!GRPNm!=" > Nul 2> Nul
  )
 )
 Exit /B 0

 :GetArgs
 If "%~1" == "" Exit /B 0
 Set "Param=%~1"
 Echo/"%~1"|"%__AppDir__%findstr.exe" /LIC:"/D" > Nul 2> Nul && (Set "#STDOut=1"&Shift&Goto :GetArgs)
 Echo/"%~1"|"%__AppDir__%findstr.exe" /LIC:"/A:" > Nul 2> Nul && (Set "GRPNm=!Param:*/A:=!"&(If "!Param:*/A:=!"=="" %Usage:###=/A:Groupname required%)&Shift&Goto :GetArgs)
 Echo/"%~1"|"%__AppDir__%findstr.exe" /LIC:"/O:" > Nul 2> Nul && (Set "SwParam=!Param:*/O:=!"&(If Not "!Param:/O:=!"=="" (Set "#ORP#=1")Else %Usage:###=/O:#Arg not Supplied%)&Shift&Goto :GetArgs)
 Echo/"%~1"|"%__AppDir__%findstr.exe" /LIC:"/F:" > Nul 2> Nul && (Set "SwFParam=!Param:*/F:=!"&(If Not "!Param:/F:=!"=="" (Set "#FP#=1")Else %Usage:###=/F:Filepath.ext not Supplied%)&Shift&Goto :GetArgs)
 Echo/"%~1"|"%__AppDir__%findstr.exe" /LIC:"/S:" > Nul 2> Nul && (Set "SubEl=!Param:*/S:=!"&(If "!Param:/S:=!"=="" %Usage:###=/S:Sub Element not Supplied%)&Shift&Goto :GetArgs)
 Set Inset=!Inset! %1
 Shift&Goto :GetArgs
 Rem ::: Index count for each array GROUP stored in #GRPNm
Another script (macro) for searching an array for a given value:

Code: Select all

@echo off & Setlocal DisableDelayedExpansion
	(Set LF=^


	%= Above Empty lines Required =%)
	Set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
::: { Array Search Macro <{Search Value}> <{Array Class Name}>
    Set Search.Array=For %%n in (1 2) Do if %%n==2 (%\n%
        For /F "Tokens=1,2 Delims={}" %%G in ("!Search.Item!") Do (%\n%
            For %%s in ("%%~G") do (%\n%
                    For /F "USEBACKQ Tokens=1,2 Delims==" %%i in (`"Set %%~H["`) Do (%\n%
                        For /F "USEBACKQ Tokens=* Delims=" %%f in (`Echo("%%~j"^^^|%__AppDir__%Findstr.exe /I "%%~s"`) do (%\n%
                                If /I "%%~s" == "%%~f" (Echo %%~f found in %%~i = %%~j)%\n%
                        )%\n%
                    )%\n%
            )%\n%
        )%\n%
    ) Else Set Search.Item=
::: }
	Set Search.Time=Echo/!Time!
Setlocal EnableDelayedExpansion
(For /L %%A in (1,2,3) do For /L %%B in (1,1,10) do Set /A ArrayName[%%A][%%B]=%%A * %%B)&REM Example Array
Set "ArrayName[2][8]=test"& Set "ArrayName[1][6]=string check"
%Search.Time% %= Search via Subroutine =%
For %%A in (3 5 8 12 test string "String Check") do Call :Search.Array "%%~A" ArrayName
%Search.Time% %= Search via Macro =%
For %%A in (3 5 8 12 test string "String Check") do %Search.Array%{%%~A}{ArrayName}
%Search.Time%
%Search.Array%{18}{ArrayName}
%Search.Time%
Pause & Endlocal & Exit /B
:Search.Array <Search Value> <Array Class Name>
(For %%S in ("%~1") do (
    For /F "USEBACKQ Tokens=1,2 Delims==" %%A in (`"Set %~2["`) Do (
        For /F "USEBACKQ Tokens=* Delims=" %%F in (`Echo("%%~B"^|%__AppDir__%Findstr.exe /I "%%~S"`) do (
            If /I "%%~S" == "%%~F" (Echo %%~S found in %%~A = %%~B)
        )&REM remove /I switch from FindStr if case sensitivity required
    )
)) & Exit /B
Script for performing an alphanumerical order sort on array values:

Code: Select all

@Echo Off
Set "Usage=Echo/&Echo/%~n0 ["/F:filepath.ext" ^| "/A:Array Group Name"] & Exit /B 1"
IF "%~1"=="" %Usage%
IF "%~1"=="/?" %Usage%
Set "Inset=%~1"
Set "Switch=%Inset:~1,1%"
Call Set "Inset=%%Inset:/%Switch%:=%%"
Echo/%Switch%|Findstr /LIC:F > Nul && (
 (For /F "UseBackQ Delims=" %%G in (`Type "%Inset%" ^| Sort`)Do (Echo/%%~G)) 2> Nul || (Echo/Invalid Filepath:"%Inset%"&%Usage%)
 Exit /B 0
)
If Not "!Comspec!"=="%Comspec%" (Echo/&Echo/Usage Error - Ensure Delayed Expansion is enabled with:&Echo/Setlocal EnableDelayedExpansion& Exit /B 1)
Echo/%Switch%|Findstr /LIC:A > Nul && (For /F "Tokens=1,2 Delims==" %%G in ('Set %Inset%')Do Echo/%%H)>"%TEMP%\__Sort.txt"
Set "#$#=0"
(For /F "UseBackQ Delims=" %%G in (`Type "%TEMP%\__Sort.txt" ^| Sort`)Do (
  For %%x in ("%Inset%[!#$#!]") Do (
   Setlocal DisableDelayedExpansion
   Endlocal & Set "%%~X=%%~G"
  )
   Set /A "#$#+=1"
 )
)
Del /Q "%TEMP%\__Sort.txt"
Exit /B 0
Rem ::: Sorts STRINGS alphanumericaly. Not suited to Integer strings of varying length.
Rem ::: Can Sort text files or Arrays
Rem ::: With the manner sort process strings, when numerical strings are sorted Single digits will be treated as a higher value than multiple digits that
Rem ::: begin with a lesser value, as the sort is applied on the basis of character value in the string position, not the overall strings value.
Rem ::: For a given position in a string Character sort order is: [0-9][a-z]
Rem ::: Case is ignored
Lastly a script to sort arrays containing Integer values from lowest to highest / highest to lowest value

Code: Select all

@ECHO OFF
Set "UseErr=Echo/&Echo/Usage Error - Ensure command extensions and Delayed Expansion are enabled with: &Echo/Setlocal EnableExtensions EnableDelayedExpansion&Echo/ or from the command line:&Echo/CMD /V:On /K&Exit /B 1"
If Not "!Comspec!"=="%Comspec%" (%UseErr%)
(Set "GRPNm="&Set "S_Offset="&Set "#STDOut="&Set "indNm="&Set "nGRPNm="&Set "#Order="&Set "Inset="&Set "Usage=Echo/###&Echo/%~n0 /A:Groupname /I:Indexname [/H^|/L]&Exit /B 1") > Nul 2> Nul
Call :GetArgs %*
If Errorlevel 1 Exit /B 1
If "!GRPNm!"=="" %Usage:###=/A:Groupname required%
If "!nGRPNm!"=="" %Usage:###=/N:New Groupname required%
If "!IndNm!"=="" %Usage:###=/I:Index Name required%
If Not "%#Order%"=="" (Call :Sort%#Order% !nGRPNm! !indNm! !Inset!) Else (%Usage:###=Sort Order Required /H or /L%)
Exit /B 0
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Subroutines for Population of Arrays with numeric values in sorted order.
:sortL <Element_VarName> <Element_Index_VarName> <Variable Names containing the values to be Sorted and Populated to the Array>
REM Adjust array Index Number to account for Element_VarName and Element_Index_VarName:	
        Set "%2=0"
        FOR %%P In (%*) DO If Not "%%P"=="%1" If Not "%%P"=="%2" If Not "%%P"=="" (
		Set "%1[!%2!]=!%%P!"
		Set /A "%2+=1"
	)

REM Sort the Array using an Offset and Temporary variable to exchange values within nested For Loops.
	For /L %%a In (1,1,!%2!) Do (
		Set /A "S_Offset=%%a - 1"
		For /L %%b IN (0,1,%%a) DO (
			If not %%b==%%a For %%c in (!S_Offset!) DO (
				IF !%1[%%c]! LEQ !%1[%%b]! (
					Set "tmpV=!%1[%%c]!"
					Set "%1[%%c]=!%1[%%b]!"
					Set "%1[%%b]=!tmpV!"
				)
			)
		)
	)
	Set /A %2-=1
	If "!#STDOut!"=="1" For /L %%G in (0 1 !%2!)Do Echo/%1[%%G]=!%1[%%G]!
	Exit /B 0
:sortH <Element_VarName> <Element_Index_VarName> <Variable Names containing the values to be Sorted and Populated to the Array>
REM Adjust array Index Number to account for Element_VarName and Element_Index_VarName:		
	Set "%2=0"
	FOR %%P In (%*) DO If Not "%%~P"=="%~1" If Not "%%~P"=="%2" If Not "%%P"=="" (
		Set "%1[!%2!]=!%%~P!"
		Set /A "%2+=1"
	)
REM Sort the Array using an Offset and Temporary variable to exchange values within nested For Loops.
	For /L %%a In (1,1,!%2!) Do (
		Set /A "S_Offset=%%a - 1"
		For /L %%b IN (0,1,%%a) DO (
			If not %%b==%%a For %%c in (!S_Offset!) DO (
				IF Not !%1[%%c]! LSS !%1[%%b]! (
					Set "tmpV=!%1[%%c]!"
					Set "%1[%%c]=!%1[%%b]!"
					Set "%1[%%b]=!tmpV!"
				)
			)
		)
	)
	Set /A %2-=1
	If "!#STDOut!"=="1" For /L %%G in (0 1 !%2!)Do Echo/%1[%%G]=!%1[%%G]!
	Exit /B 0
:GetArgs
 If "%~1" == "" (
  (For /F "Tokens=1,2 Delims==" %%G in ('Set !GRPNm![')Do Set "Inset=!Inset! %%G") > Nul 2> Nul || (%Usage:###=Usage Error - Target Array is not defined%)
  Exit /B 0
 )
 Set "Param=%~1"
 Echo/"%~1"|"%__AppDir__%findstr.exe" /LIC:"/H" > Nul 2> Nul && (Set "#Order=H"&Shift&Goto :GetArgs)
 Echo/"%~1"|"%__AppDir__%findstr.exe" /LIC:"/L" > Nul 2> Nul && (Set "#Order=L"&Shift&Goto :GetArgs)
 Echo/"%~1"|"%__AppDir__%findstr.exe" /LIC:"/D" > Nul 2> Nul && (Set "#STDOut=1"&Shift&Goto :GetArgs)
 Echo/"%~1"|"%__AppDir__%findstr.exe" /LIC:"/N:" > Nul 2> Nul && (Set "nGRPNm=!Param:*/N:=!"&(If "!Param:*/N:=!"=="" %Usage:###=/N:New Group Name required%)&Shift&Goto :GetArgs)
 Echo/"%~1"|"%__AppDir__%findstr.exe" /LIC:"/A:" > Nul 2> Nul && (Set "GRPNm=!Param:*/A:=!"&(If "!Param:*/A:=!"=="" %Usage:###=/A:Group Name required%)&Shift&Goto :GetArgs)
 Echo/"%~1"|"%__AppDir__%findstr.exe" /LIC:"/I:" > Nul 2> Nul && (Set "IndNm=!Param:*/I:=!"&(If "!Param:*/I:=!"=="" %Usage:###=/A:Index Name required%)&Shift&Goto :GetArgs)
 Shift&Goto :GetArgs
Tempted to rework the switches and flow to combine all the scripts into one.

T3RRY
Posts: 58
Joined: 06 May 2020 10:14

Re: Batch array scripts, to make life easier

#2 Post by T3RRY » 05 Sep 2020 03:57

The all in one package is complete

Modes:
[Def] Define, modify or clear an array.
[Def] Switches: [/A:Groupname] [/F:Filepath.ext] [/D] [/O:Index#Arg] [/E:Element Sub value]
[Sort-int] Sorts array by lowest or highest value using /L or /H switches
[Sort-int] Switches: [/A:Groupname] [/N:New Groupname] [/L|/H] [/D]
[Sort-str] Sorts an array or text files string values using alphanumerical order of sort: [0-9][a-z]
[Sort-str] Switches: [/A:Groupname] [/F:Filepath.ext] [/D]
[Find-searchstring] Searches an array for the string value supplied.
[Find-searchstring] Switches: [/A:Groupname]

Note:
Switch /D uses Echo to output the defined / modified or sorted Array to STDout
Attachments
$Array.txt
(9.07 KiB) Downloaded 11 times
Last edited by T3RRY on 05 Sep 2020 09:17, edited 1 time in total.

aGerman
Expert
Posts: 3934
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Batch array scripts, to make life easier

#3 Post by aGerman » 05 Sep 2020 05:48

Anmerkung 2020-09-05 134427.png
Anmerkung 2020-09-05 134427.png (40.66 KiB) Viewed 345 times

¯\_(ツ)_/¯ Maybe some examples would be helpful.

Steffen

siberia-man
Posts: 165
Joined: 26 Dec 2013 09:28
Contact:

Re: Batch array scripts, to make life easier

#4 Post by siberia-man » 05 Sep 2020 07:22

A total absence of arrays in batches allows to implement them in different ways:
-- arr[idx] (or something similar to)
-- arr sep idx (like arr.idx or arr_idx etc)

I think that the actual implementation of batch arrays lies on authors of the scripts they develop.

In the other hand, if they need array, perhaps, they should rethink their script to avoid array usage.

aGerman
Expert
Posts: 3934
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Batch array scripts, to make life easier

#5 Post by aGerman » 05 Sep 2020 08:26

siberia-man wrote:
05 Sep 2020 07:22
In the other hand, if they need array, perhaps, they should rethink their script to avoid array usage.
I agree. Associative arrays need a name-value pair for every element wich inflates the environment block in case of Batch. Once I was thinking about using the registry along with its REG_MULTI_SZ type. But never actually tried to figure out if this was possible...

Steffen

T3RRY
Posts: 58
Joined: 06 May 2020 10:14

Re: Batch array scripts, to make life easier

#6 Post by T3RRY » 05 Sep 2020 09:36

aGerman wrote:
05 Sep 2020 05:48
Anmerkung 2020-09-05 134427.png


¯\_(ツ)_/¯ Maybe some examples would be helpful.

Steffen
Helpful to be sure, there was also a change I made and failed to test appropriately before the last upload that cut off a lot of the Usage Error messages.

That's now been fixed, and more detailed usage info provided.
Each mode can now have it's help displayed using the single parameter: /M:Modename
All modes basic usage info is already displayed when calling the file with no parameters.

Some note on your output: (Line numbers commencing after cmd /V:On /K)
Line 1: Array would be defined, but no output displayed with the /D switch missing. /D switch displays dynamically as arrays are defined / modified when used.

Line 2: Calling the Def Mode with no elements clears the array. Def Mode Usage:

Code: Select all

$Array /M:Def
Output:

C:\Users\tcdou>$Array /M:Def
/A:Groupname Required
Call $Array [/M:Def] [/A:Groupname] ["element0" ~ "element#"] [/F:Filepath.ext] [/E:"Element sub value"]
- Assign each line in the given filepath plus element parameters to the Array
Call $Array [/M:Def] [/A:Groupname] REM : Clears the Array for the given Group Name
Call $Array [/M:Def] [/A:Groupname] [element] [element] [/O:Index#Arg] REM : Overides Elements from the index supplied
Line 3: As line two cleared the array, this is the correct error message. Had not your last line cleared the arrray, You would instead have recieved a missing parameter message as no /H or /L switch was used to declare sort order

Line 4: the /E: Switch is to enable a value to be assigned to the array element being assigned to the Array Group. this process is unfortunately rather slow if assigning singular elements with each Call to $Array.

An example script showing some usages:

Code: Select all

@Echo off
::: { Creates variable /AE = Ascii-27 escape code.
::: - http://www.dostips.com/forum/viewtopic.php?t=1733
::: - https://stackoverflow.com/a/34923514/12343998
:::
::: - /AE (Alt 146) can be used  with and without DelayedExpansion.
    Setlocal
    For /F "tokens=2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
        Endlocal
        Set "/AE=%%a"
    )
::: }
If Defined #CI Set #CI=
::: { Assigns ANSI color code values to each color, then builds an Array containing those color values to be accessed using random number.
	Setlocal EnableExtensions EnableDelayedExpansion
	Call $Array /A:CI /M:Def
	Set /A Red=31,Yellow=33,Green=32,Blue=34,Purple=35,Cyan=36,White=37,Gray=90,Pink=91,Beige=93,Aqua=94,Magenta=95,Teal=96,Off=0,Black=30
	For %%A in (Red,Yellow,Green,Blue,Off,Pink,Beige,Gray,Purple,Cyan,White,Aqua,Magenta,Teal,Black) do Call $Array /A:CI /M:Def "%%~A" "/E:!/AE![!%%A!m" /D
::: }
Set /A #CI-=1
For /L %%. in (0,1,!#CI!) Do for /F "Tokens=1,2 Delims==" %%G in ('Set CI[%%.]')Do Echo/!%%H!%%G=%%H!Off!
Call $Array /A:CI /M:Sort-str /D
rem clear array
Call $Array /A:CI /M:Def
Set CI[
Endlocal
Goto :Eof

T3RRY
Posts: 58
Joined: 06 May 2020 10:14

Re: Batch array scripts, to make life easier

#7 Post by T3RRY » 06 Sep 2020 10:31

siberia-man wrote:
05 Sep 2020 07:22
A total absence of arrays in batches allows to implement them in different ways:
-- arr[idx] (or something similar to)
-- arr sep idx (like arr.idx or arr_idx etc)

I think that the actual implementation of batch arrays lies on authors of the scripts they develop.
I very much agree with the principle here, but few people these days would be inclined to learn how to script such functions in batch

Most of the functionality the previous scripts provide can be achieved in a much more compact and efficient fashion:

Code: Select all

@Echo off & CD "%~dp0"
 Set "$Def=For %%n in (1 2)Do if %%n==2 ((If "!#$A!"=="" (Set "#$A=0"))&(For %%G in (!elements!)Do (Set "$A[!#$A!]=%%~G"&Set /A "#$A+=1")))Else Set elements="
 Set "$Find=Set "Fnd=0"&For %%n in (1 2)Do if %%n==2 (For %%G in ("!string!")Do (For /F "Tokens=1,2 Delims==" %%1 in ('Set $A[')Do (If /I "%%~G"=="%%2" (Set "Fnd=1"&Echo/%%2 in Var %%1)))&(If not "!Fnd!"=="1" (Echo/!String! not found in $A&Set "Fnd=0")))Else Set string="
 Set "/D=For /L %%G in (0 1 !#$A!)Do If not "!$A[%%G]!"=="" Echo/$A[%%G]=!$A[%%G]!"
 Set "/C=(For /F "Tokens=1,2 Delims==" %%G in ('Set $A[')Do (Set "%%G=")& Set "#$A=") > Nul 2> Nul"
 Set "Sort/L=(((For /F "Tokens=1,2 Delims==" %%G in ('Set $A[')Do Echo/%%H)>"%TEMP%\__Sort.txt")&(Set "#$A=0"&For /F "UseBackQ Delims=" %%G in (`Type "%TEMP%\__Sort.txt" ^| Sort`)Do (For %%x in ("$A[!#$A!]") Do (Setlocal DisableDelayedExpansion&&Endlocal&Set "%%~x=%%~G")&Set /A "#$A+=1"))&Set /A "#$A-=1")"
 Set "Sort/H=(((For /F "Tokens=1,2 Delims==" %%G in ('Set $A[')Do Echo/%%H)>"%TEMP%\__Sort.txt")&(Set "#$A=0"&For /F "UseBackQ Delims=" %%G in (`Type "%TEMP%\__Sort.txt" ^| Sort /R`)Do (For %%x in ("$A[!#$A!]") Do (Setlocal DisableDelayedExpansion&&Endlocal&Set "%%~x=%%~G")&Set /A "#$A+=1"))&Set /A "#$A-=1")"
 Setlocal&&For /F "tokens=2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (Endlocal&Set "/AE=%%a")
rem // usage examples
 Set "TAB=	"
 Set "CIOut=(For /L %%. in (0,1,!#CI!) Do for /F "Tokens=1,2 Delims==" %%G in ('Set CI[%%.]')Do Echo/!%%H!%%G=%%H!Off!)"
 If Defined #CI Set #CI=
 Setlocal EnableExtensions EnableDelayedExpansion & Mode 1000

 %/C:$A=El%
 Set /A Red=31,Yellow=33,Green=32,Blue=34,Purple=35,Cyan=36,White=37,Gray=90,Pink=91,Beige=93,Aqua=94,Magenta=95,Teal=96,Off=0,Black=30
 For %%A in (Red,Yellow,Green,Blue,Off,Pink,Beige,Gray,Purple,Cyan,White,Aqua,Magenta,Teal,Black) do ((%$Def:$A=CI%%%A)&Set "%%A=%/AE%[!%%A!m")
 Set /A #CI-=1 > Nul
 %CIOut% & %$Find:$A=CI%Black
 %Sort/L:$A=CI% & %CIOut% & %$Find:$A=CI%Black
 %Sort/H:$A=CI% & %CIOut% & %$Find:$A=CI%Black
 Pause
 %$Def:$A=El%1 1 2 3 5 8 13 21
 %/D:$A=El%
 %$Find:$A=El%8
 %/C:$A=El%
 %$Def:$A=El%02 05 11 41 31 17 47 07 37 19 29 23 13 43 03
 %/D:$A=El%
 %$Find:$A=El%8
 %$Find:$A=El%41
 %Sort/L:$A=El%
 %/D:$A=El%
 %$Find:$A=El%41
 %Sort/H:$A=El%
 %/D:$A=El%
 %$Find:$A=El%41
Endlocal
not many would be bothered to learn how however, and a script like the above also lacks usage info, error handling or even readability for the layman to see whats going on at a glance

In the other hand, if they need array, perhaps, they should rethink their script to avoid array usage.

This is a point I'd definitely agree with. For batch in particular Lists and Substring modification offer much better performance.

Code: Select all

@Echo Off& Setlocal DisableDelayedExpansion
 Set "List/E=Set "#n=0"&For %%n in (1 2)Do if %%n==2 (For %%G in (!ListV!)Do If "!#n!"=="i#" (Echo/%%~G& Set /A "#n+=1")Else (Set /A "#n+=1"))Else Set ListV="
 Set "List/D=Set "#$L=0"&For %%n in (1 2)Do if %%n==2 (For %%G in (!$L!)Do (Echo/%%~G&Set /A "#$L+=1"))Else Set $L="
 Set "List/D/V=Set "#$L=0"&Set "$$L="&For %%n in (1 2)Do if %%n==2 (For %%G in (!$L!)Do (Set "%%~G" > Nul &Set /A "#$L+=1"))Else Set $L="
rem // Usage Examples:
 Set "Tab=	"
 For /F %%a in ('echo prompt $E ^| cmd')do (Set "/E=%%a[^!C^!mC")
 Setlocal EnableExtensions EnableDelayedExpansion & Mode 1000
Echo/Define Lists:&Echo/%%List/D:$L-ListVarname%%"List" "quoted" "values" ...&Echo/
Echo/Define Lists with Matched values:&Echo/%%List/D/V:$L-ListVarname%%"var=val" "var2=val" ...&Echo/
 %List/D/V:$L=str%"Red=31" "Yellow=33" "Green=32" "Blue=34" "Purple=35" "Cyan=36" "White=37" "Gray=90" "Pink=91" "Beige=93" "Aqua=94" "Magenta=95" "Teal=96" "Off=0" "Black=30"
 Echo/!TAB!%/E:C=Red%!TAB!%/E:C=Green%!TAB!%/E:C=Aqua%!TAB!%/E:C=Magenta%!TAB!%/E:C=Yellow%!TAB!%/E:C=Gray%!TAB!%/E:C=Teal%!TAB!%/E:C=Pink%!TAB!%/E:C=White%
 Set "/E=%/E:mC=m^!C^!%"
 Echo/!TAB!%/E:C=Red%!TAB!%/E:C=Green%!TAB!%/E:C=Aqua%!TAB!%/E:C=Magenta%!TAB!%/E:C=Yellow%!TAB!%/E:C=Gray%!TAB!%/E:C=Teal%!TAB!%/E:C=Pink%!TAB!%/E:C=White%
Echo/&Echo/Extract value from list by index #:&Echo/%%List/E:i#=indexValue%%^^!ListVarname^^!&Echo/
 For /L %%. in (0,2,!#str!) Do (Set "el#=%%."&%List/E:i#=!el#!%!str!)
Choice /M "Exit" /C:E /T 10 /D E
Endlocal&Endlocal&Goto :Eof

Post Reply