Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- @Echo Off
- SetLocal EnableDelayedExpansion
- :: Небольшое демо
- Call :Array new Test "'random string','123','34',567,abcd,'TEST1',test2,'',qWerty"
- Echo View array:
- Call :Array echo Test
- Echo ==============
- Call :Array shuffle Test
- Echo View after shuffle:
- Call :Array echo Test
- Echo ==============
- Call :Array get Test 4 out
- Echo Element no.4:
- Echo [4] !out!
- Echo ==============
- Echo Search:
- Call :Array find Test "s" f
- Call :Array find Test "s" f out
- Echo Elements = [!out!]
- Echo ==============
- pause
- :Array (action,name,data)
- :: Обработчик команды
- For %%A In (new,wipe,copy,add,delete,set,sort,shuffle,get,find,view,echo) Do (
- If "%~1"=="%%A" (
- Call :[]%%A %2 %3 %4 %5 &:: Передаём аргументы далее, исключая саму команду
- Exit /B 0
- )
- )
- :: Вывод справки если команда не указана или не существует
- :: Ага, мой английский ужасен.
- Echo. Arrays for CMD
- Echo. Inquisitor, 2011
- Echo. USAGE: Call :Array ^<action^> ^<array name^> ^<data^>
- Echo. Actions:
- Echo. new - Create array
- Echo. Call :Array new A "'one','two','three'"
- Echo. wipe - Delete array
- Echo. Call :Array wipe A
- Echo. copy - Create copy of array
- Echo. Call :Array copy A B
- Echo. add - Add element to existing array
- Echo. Call :Array add A "four"
- Echo. Call :Array add A "'some more','elements'"
- Echo. delete - Delete item from array
- Echo. Call :Array delete A 2
- Echo. set - Change the value of the item by its number in the index
- Echo. Call :Array set A 1 "test"
- Echo. sort - Sort array
- Echo. Call :Array sort A
- Echo. shuffle - Shuffle array in random order
- Echo. Call :Array shuffle A
- Echo. get - Get the value of element to specified variable
- Echo. use 'index' instead of number to obtain array element count
- Echo. Call :Array get A 3 ^<variable name^>
- Echo. find - Find all elements with this value
- Echo. if defined var name, returns array with element numbers
- Echo. mode: s - regular, i - case insensitive, f - fuzzy
- Echo. Call :Array find A "string" ^<mode^> ^<variable name^>
- Echo. view - Print the array elements
- Echo. Call :Array view A
- Echo. echo - Print the array elements w/ index
- Echo. Call :Array echo A
- Exit /B 2
- :[]new (name,data)
- :: Проверки
- If "%~1"=="" (Echo Name not specified&&Exit /B 1)
- If "%~2"=="" (Echo Array data is empty&&Exit /B 1)
- If Defined $%~1[index] (Echo Array already exist&&Exit /B 1)
- Set "ArrayData=%~2"
- Set /A i=0
- :: Разбираем входящие данные и создаём элементы. Пустое значение всегда указывается как ''.
- :: Значение элемента всегда начинается с "=", этот трюк позволяет использовать пустые значения без проблем с неопределённой переменной
- For %%A In (%ArrayData:'=^"%) Do (
- Set /A i+=1
- Set "$%~1[!i!]==%%~A"
- )
- Set "$%~1[index]=!i!"
- Exit /B
- :[]echo (name)
- :: Проверки
- If "%~1"=="" (Echo Name not specified&&Exit /B 1)
- If Not Defined $%~1[index] (Echo This array not existed&&Exit /B 1)
- :: Выводим массив в понятном человеку виде
- Echo. %~1[]
- For /L %%A In (1,1,!$%~1[index]!) Do (
- Echo [%%A]: "!$%~1[%%A]:~1!"
- )
- Exit /B
- :[]view (name)
- :: Проверки
- If "%~1"=="" (Echo Name not specified&&Exit /B 1)
- If Not Defined $%~1[index] (Echo This array not existed&&Exit /B 1)
- :: Выводим массив без лишних свистоперделок, можно перенаправить в файл, например.
- For /L %%A In (1,1,!$%~1[index]!) Do (
- Echo.!$%~1[%%A]:~1!
- )
- Exit /B
- :[]wipe (name)
- :: Проверки
- If "%~1"=="" (Echo Name not specified&&Exit /B 1)
- If Not Defined $%~1[index] (Echo This array not existed&&Exit /B 1)
- :: Очищаем все элементы и индекс
- For /L %%A In (1,1,!$%~1[index]!) Do (
- Set "$%~1[%%A]="
- )
- Set "$%~1[index]="
- Exit /B
- :[]add (name,data)
- :: Проверки
- If "%~1"=="" (Echo Name not specified&&Exit /B 1)
- If Not Defined $%~1[index] (Echo This array not existed&&Exit /B 1)
- :: Добавляем значения в массив. Можно бы было слить с :[]new, там почти тот же код, но лень
- Set "ArrayData=%~2"
- Set i=!$%~1[index]!
- For %%A In (,%ArrayData:'=^"%) Do (
- Set /A i+=1
- Set "$%~1[!i!]==%%~A"
- )
- Set "$%~1[index]=!i!"
- Exit /B
- :[]copy (name1,name2)
- :: Проверки
- If "%~1"=="" (Echo First name not specified&&Exit /B 1)
- If "%~2"=="" (Echo Second name not specified&&Exit /B 1)
- If Not Defined $%~1[index] (Echo Can't copy nonexistent array&&Exit /B 1)
- If Defined $%~2[index] (Echo Array already exist&&Exit /B 1)
- :: Полностью переносим содержимое массива в новый
- For /L %%A In (1,1,!$%~1[index]!) Do (
- Set "$%~2[%%A]=!$%~1[%%A]!"
- )
- Set "$%~2[index]=!$%~1[index]!"
- Exit /B
- :[]delete (name,element)
- :: Проверки
- If "%~1"=="" (Echo Name not specified&&Exit /B 1)
- If "%~2"=="" (Echo Element not specified&&Exit /B 1)
- If Not Defined $%~1[index] (Echo This array not existed&&Exit /B 1)
- If Not Defined $%~1[%~2] (Echo Element not found&&Exit /B 1)
- :: Делаем копию и удаляем оригинал
- Call :[]copy "%~1" "$copy_%~1"
- Call :[]wipe "%~1"&&Set "$%~1[index]=0"
- :: Добавляем в исходный массив все элементы, кроме указанного.
- :: Медленно, чёрт побери. Фактически это полная пересборка. Но по другому тяжело организовать удаление со сдвигом нумерации.
- :: Сокращение числа вызовов :[]add, как это реализовано в :[]shuffle, не приносит заметного прироста производительности
- For /L %%A In (1,1,!$$copy_%~1[index]!) Do (
- If Not "%%A"=="%~2" Call :[]add "%~1" '!$$copy_%~1[%%A]:~1!'
- )
- :: Удаляем массив если в нём ничего не осталось и чистим за собой
- If "!$%~1[index]!"=="0" Set "$%~1[index]="
- Call:[]wipe "$copy_%~1"
- Exit /B
- :[]set (name,element,data)
- :: Проверки
- If "%~1"=="" (Echo Name not specified&&Exit /B 1)
- If "%~2"=="" (Echo Element not specified&&Exit /B 1)
- If Not Defined $%~1[index] (Echo This array not existed&&Exit /B 1)
- If Not Defined $%~1[%~2] (Echo Element not found&&Exit /B 1)
- :: Устанавливаем новое значение.
- Set "ElementValue=%~3"
- :: Перестраховка
- Set "$%~1[%~2]==!ElementValue:'=!"
- Exit /B
- :[]sort (name)
- :: Проверки
- If "%~1"=="" (Echo Name not specified&&Exit /B 1)
- If Not Defined $%~1[index] (Echo This array not existed&&Exit /B 1)
- :: Сбрасываем массив во временный файл. Без него никак, выхлоп функции нельзя передать через пайп
- Set tmpDump=%Temp%\a_%random%%random%.tmp
- Call :[]view "%~1">"%tmpDump%"
- :: Сортировка. Find служит для вывода не печатаемых в обычной ситуации пустых строк.
- Call :[]wipe "%~1"&&Set "$%~1[index]=0"
- For /F "eol= delims=] tokens=1,*" %%A In ('Sort "%tmpDump%"^|Find /V /N ""') Do (
- Call :[]add "%~1" "'%%B'"
- )
- Del "%tmpDump%"
- Exit /B
- :[]shuffle (name)
- :: Проверки
- If "%~1"=="" (Echo Name not specified&&Exit /B 1)
- If Not Defined $%~1[index] (Echo This array not existed&&Exit /B 1)
- :: Делаем копию, которая служит источником данных во время рандомной выборки
- Call :[]copy "%~1" "$shuffle_%~1"
- :: Удаляем исходный массив и заново наполняем его
- Call :[]wipe "%~1"&&Set "$%~1[index]=0"
- Set "rndSequence=,"&&Set i=0
- :rndseq :: Почему не цикл? Чтобы не играться с экранированием вложенных скобок, да и более читаемо
- Echo !random!!random!>nul
- Set /A rnd=1+!$$shuffle_%~1[index]!*%random%/32768
- If "!rndSequence!"=="!rndSequence:,%rnd%,=!" (
- Set rndSequence=!rndSequence!!rnd!,
- Set /A i+=1
- )
- If !i! GEQ !$$shuffle_%~1[index]! (
- Set "ArrayData="
- :: Формируем строку для добавления
- For %%A In (%rndSequence%) Do (
- Call :StrLen ArrayData &:: Если данные превысили половину макс. размера переменной, добавляем в массив и чистим
- Set ArrayData=!ArrayData!,'!$$shuffle_%~1[%%~A]:~1!'
- If !ArrayData.strlen! GEQ 4096 (
- Call :[]add "%~1" "!ArrayData!"
- Set "ArrayData="
- )
- )
- Call :[]add "%~1" "!ArrayData!" &:: Добавляем остаток в случае большого массива или все данные для маленького
- Call :[]wipe "$shuffle_%~1"
- Exit /B
- )
- GoTo :rndseq
- :[]get (name,element,out:variable)
- :: Проверки
- If "%~1"=="" (Echo Name not specified&&Exit /B 1)
- If "%~2"=="" (Echo Element not specified&&Exit /B 1)
- If "%~3"=="" (Echo Output name not specified&&Exit /B 1)
- If Not Defined $%~1[index] (Echo This array not existed&&Exit /B 1)
- If Not Defined $%~1[%~2] (Echo Element not found&&Exit /B 1)
- Set "%~3=!$%~1[%~2]:~1!"
- Exit /B
- :[]find (name,search_string,mode,out:variable)
- :: Проверки
- If "%~1"=="" (Echo Name not specified&&Exit /B 1)
- If Not Defined $%~1[index] (Echo This array not existed&&Exit /B 1)
- If "%~2"=="" (Echo Search string is empty&&Exit /B 1)
- If "%~3"=="" (Echo Search mode not specified&&Exit /B 1)
- Set SearchMode=/i/s/f/
- If "!SearchMode!"=="!SearchMode:/%~3/=!" (Echo Invalid search mode, see help&&Exit /B 1)
- :: Сбрасываем массив во временный файл. При нескольких тысячах элементов есть разница,
- :: вызывать find на каждую строку или лишь единожды
- Set tmpDump=%Temp%\a_%random%%random%.tmp
- Call :[]view "%~1">>"%tmpDump%"
- Set "SearchResult="
- :: Обычный поиск, нужно точное совпадение, вплоть до регистра символов.
- If "%~3"=="s" (
- For /F "tokens=1 delims=:" %%A In ('Findstr /XNC:"%~2" "%tmpDump%"') Do (Set SearchResult=!SearchResult! %%A)
- )
- :: Обычный, но независимо от регистра
- If "%~3"=="i" (
- For /F "tokens=1 delims=:" %%A In ('Findstr /XINC:"%~2" "%tmpDump%"') Do (Set SearchResult=!SearchResult! %%A)
- )
- :: Нечёткий поиск, регистронезависим и находит все включения строки
- If "%~3"=="f" (
- For /F "tokens=1 delims=:" %%A In ('Findstr /INC:"%~2" "%tmpDump%"') Do (Set SearchResult=!SearchResult! %%A)
- )
- :: Если указано имя переменной для вывода, выдаём последовательность номеров туда, иначе - просто показываем строки и номера.
- If Not "%~4"=="" If Defined SearchResult (Set "%~4=!SearchResult:~1!") Else (Set "%~4=")
- If "%~4"=="" If Defined SearchResult (
- Echo. %~1[], searched for "%~2"
- For %%A In (!SearchResult:~1!) Do (Echo [%%A]: "!$%~1[%%A]:~1!")
- ) Else (
- Echo Not found
- )
- Del "%tmpDump%"
- Exit /B
- :StrLen (name,out:name.strlen]
- :: Получение размера строки по имени переменной
- Set StrLen.S=A!%~1!
- Set StrLen=0
- For /L %%P In (12,-1,0) Do (
- Set /A "StrLen|=1<<%%P"
- For %%I In (!StrLen!) Do If "!StrLen.S:~%%I,1!"=="" Set /A "StrLen&=~1<<%%P"
- )
- Set "%~1.strlen=!StrLen!"
- Exit /B
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement