Advertisement
Guest User

array.bat

a guest
Sep 16th, 2010
2,412
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Batch 36.21 KB | None | 0 0
  1. @ECHO off
  2. rem Включаем отложеную подстановку переменных (ENABLEDELAYEDEXPANSION)
  3. rem Нужно для того, чтобы переменные виже !var! подставлялись в момент выполнения
  4. rem В противном случае внутри блоков if переменные нельзя будет менять
  5. rem Включием расширенную обработку комманд (ENABLEEXTENSIONS)
  6. rem В частности для того, чтобы можно было использовать параметр /I в if.
  7. setlocal ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS
  8.  
  9.  
  10. echo Создание массива А и вывод:
  11. call :array new A "'one','two','three','foo','bar'"
  12. call :array dump A
  13. echo.
  14. echo Добавление к массиву A элементов из набора
  15. call :array add A "'first line' 'Вторая строка' 12 54" !
  16. call :array dump A
  17. echo.
  18. echo Поиск строки BAR
  19. call :array find A "BAR" i
  20. echo Найдено в позиции !_l!
  21. echo.
  22. echo Удаление элементов 3 5 8
  23. call :array del A "3 5 8"
  24. call :array dump A
  25. echo.
  26. echo Удаление элемента two
  27. call :array find A Two i
  28. call :array del A !_l!
  29. call :array dump A
  30. echo.
  31. echo Сортировка массива
  32. call :array sort A
  33. call :array dump A
  34.  
  35.  
  36.  
  37.  
  38. goto :eof
  39.  
  40. goto :exit
  41.  
  42. rem =====  Arrays =====
  43. rem Важно помнить, что после каждого вызова функции удаляются все переменные, начинающиеся на __
  44. :array
  45.     rem Сохранение аргументов в локальных переменных
  46.     rem чтобы можно было обращать отложенным методом !__1!
  47.     rem ~ - убрать кавычки
  48.     set __1=%~1
  49.     set __2=%~2
  50.     set __3=%~3
  51.     set __4=%~4
  52.     set __5=%~5
  53.     set __6=%~6
  54.  
  55.    
  56.     rem == create ==
  57.     rem Создание массива
  58.     rem call :array create имя_массива [размер=0] [начальные значения=0]
  59.     if /I "!__1!"=="create" (
  60.  
  61.         rem Имя массива
  62.         if "!__2!"=="" (
  63.             echo Не указано имя массива
  64.             goto :eof
  65.         )
  66.         set _name=array_!__2!
  67.        
  68.         rem Размер
  69.         set /a _count=0
  70.         if not "!__3!"=="" (
  71.             set /a _count = !__3!
  72.         )
  73.        
  74.         rem Начальные значения
  75.         set _defval=0
  76.         if not "!__4!"=="" (
  77.             set _defval=!__4!
  78.         )
  79.        
  80.         rem Удаление массива, если существует c таким же именем
  81.         rem Можно было не удалять все переменные, а только оставшиеся после перезаписи, но может быть как-нибудь потом
  82.         call :array_del_ifdef !__2!
  83.        
  84.         set /a __maxindex=!_count!-1
  85.        
  86.         for /l %%i in (0,1,!__maxindex!) do set !_name!_%%i=!_defval!
  87.         set /a !_name!_count = !_count!
  88.        
  89.         set _name=
  90.         set _count=
  91.         set _defval=
  92.        
  93.     rem == new ==
  94.     rem Создание массива из набора значений
  95.     rem call :array new имя_массива "знач1, знач2, 'строка' ..."
  96.     ) else if /I "!__1!"=="new" (
  97.    
  98.         rem Имя массива
  99.         if "!__2!"=="" (
  100.             echo Не указано имя массива
  101.             goto :eof
  102.         )
  103.        
  104.         if "!__3!"=="" (
  105.             echo Не указан набор значений
  106.             goto :eof
  107.         )
  108.        
  109.  
  110.  
  111.         rem Заменяем одинарные кавычки на двойные
  112.         set _elems=!__3:'="!
  113.        
  114.         set _name=array_!__2!
  115.        
  116.         rem Удаление массива, если существует c таким же именем
  117.         call :array_del_ifdef !__2!
  118.        
  119.         rem Создаем последовательно каждый элемент и присваиваем значение
  120.         set /a __i=0
  121.         for %%i in (!_elems!) do (
  122.             rem ~ - убираем кавычки, которые необходимя просто для группировки
  123.             set !_name!_!__i!=%%~i
  124.             set /a __i+=1
  125.         )
  126.        
  127.         set /a !_name!_count=!__i!
  128.         set _elems=
  129.        
  130.     rem == get ==
  131.     rem Получение элемента массива (сохранение в переменную)
  132.     rem call :array get имя_массива [index=0] [имя_целевой_переменной=_l]
  133.     rem Если индекс отрицательный, то он считается с конца (-1 - последний, -2 - предпоследний и т.д.)
  134.     ) else if /I "!__1!"=="get" (
  135.  
  136.         rem Имя массива
  137.         if "!__2!"=="" (
  138.             echo Не указано имя массива
  139.             goto :eof
  140.         )
  141.         set __name=array_!__2!
  142.        
  143.         rem Проверка существования массива
  144.         call :array_notdefined !__2! __errors
  145.        
  146.         rem Если есть ошибки, то выходим
  147.         if not !__errors!==0 goto :eof
  148.        
  149.         rem Индекс элемента
  150.         set /a __i = 0
  151.         if not "!__3!"=="" (
  152.             set /a __i = !__3!
  153.         )
  154.  
  155.         rem Если индекс отрицательный, то считаем с конца
  156.         if !__i! LSS 0 (
  157.             rem Получаем размер
  158.             call :set __count !__name!_count
  159.             set /a __i=!__count!+!__i!
  160.         )
  161.        
  162.  
  163.         rem Имя переменной, содержащей значение элемента
  164.         set __target=!__name!_!__i!
  165.        
  166.         rem Проверка существования элемента
  167.         if not defined !__target! (
  168.             echo В массиве !__2! нет элемента с индексом !__i!
  169.             goto :eof
  170.         )
  171.        
  172.         rem Записываем значение элемента во временную переменную
  173.         call :set __value !__target!
  174.         set __var=_l
  175.         if not "!__4!"=="" (
  176.             set __var=!__4!
  177.         )
  178.        
  179.         rem Записываем в целевую
  180.         call :set !__var! __value
  181.    
  182.    
  183.    
  184.     rem == echo ==
  185.     rem Вывод значения элемента на экран
  186.     ) else if /I "!__1!"=="echo" (
  187.        
  188.         call :array get !__2! !__3! _tmpval
  189.         if not "!_tmpval!"=="" (
  190.             echo !_tmpval!
  191.         )
  192.         set _tmpval=
  193.        
  194.  
  195.     rem == list ==
  196.     rem Вывод значений списком. Может быть полезно при перенаправлении вывода
  197.     rem call :array list имя_массива
  198.     rem Пример: call :array list myArr > array.txt  - сохраняет текущий массив в файт array.txt
  199.     rem Для сохранения в кодировке cp1251 используйте save
  200.     ) else if /I "!__1!"=="list" (
  201.        
  202.         rem Имя массива
  203.         if "!__2!"=="" (
  204.             echo Не указано имя массива
  205.             goto :eof
  206.         )
  207.        
  208.        
  209.         rem Проверка существования массива
  210.         call :array_notdefined !__2! __errors
  211.        
  212.         rem Если есть ошибки, то выходим
  213.         if not !__errors!==0 goto :eof
  214.        
  215.         set __name=array_!__2!
  216.        
  217.         rem Получаем размер
  218.         call :set __count !__name!_count
  219.         set /a __maxindex=!__count!-1
  220.        
  221.         rem Вывод значений
  222.         for /l %%i in (0,1,!__maxindex!) do (
  223.             call :set __value !__name!_%%i
  224.             echo !__value!
  225.         )
  226.    
  227.     rem == save ==
  228.     rem Сохраняет массив в указанный файл в кодировке cp1251
  229.     rem call :array save имя_массива имя_файла
  230.     ) else if /i "!__1!"=="save" (
  231.    
  232.         rem Имя файла
  233.         if "!__3!"=="" (
  234.             echo Не указано имя файла
  235.             goto :eof
  236.         )
  237.        
  238.         rem Парсим вывод команды chcp, ищим номер кодовой страницы и запаминаем
  239.         for /f "usebackq tokens=2 delims=:" %%i in (`chcp`) do set /a _pageset=%%i
  240.        
  241.         rem Меняем кодовую страницу на 1251
  242.         chcp 1251>nul
  243.         rem Перенаправляем вывод list в файл
  244.         call :array list !__2! > !__3!
  245.         rem Возвращаем кодовую страницу
  246.         chcp !_pageset!>nul
  247.        
  248.        
  249.         set _pageset=
  250.        
  251.        
  252.     rem == load ==
  253.     rem Чтение в массив из файла, с кодировкой cp1251
  254.     rem call :array load имя_массива имя_файла
  255.     ) else if /i "!__1!"=="load" (
  256.         rem Имя массива
  257.         if "!__2!"=="" (
  258.             echo Не указано имя массива
  259.             goto :eof
  260.         )
  261.        
  262.         rem Имя файла
  263.         if "!__3!"=="" (
  264.             echo Не указано имя файла
  265.             goto :eof
  266.         )
  267.        
  268.         if not exist "!__3!" (
  269.             echo Файл !__3! не найден
  270.             goto :eof
  271.         )
  272.        
  273.         set _file=!__3!
  274.         set _shortname=!__2!
  275.        
  276.        
  277.         rem Удаляем массив, если сущестует
  278.         call :array_del_ifdef !__2!
  279.  
  280.         rem Парсим вывод команды chcp, ищим номер кодовой страницы и запаминаем
  281.         for /f "usebackq tokens=2 delims=:" %%i in (`chcp`) do set /a _pageset=%%i
  282.        
  283.         rem Меняем кодовую страницу на 1251
  284.         chcp 1251>nul
  285.        
  286.         rem Вносим каждую строку файла в массив
  287.         rem Используем call, чтобы выполнялось в новой кодовой странице
  288.         call :array load_unsafe !_shortname! !_file!
  289.                
  290.         rem Возвращаем кодовую страницу
  291.         chcp !_pageset!>nul
  292.  
  293.         set _name=
  294.         set _file=
  295.         set _pageset=
  296.         set _shortname=
  297.        
  298.     rem == load_unsafe ==
  299.     rem Чтение массива из файла небезопасное.
  300.     rem Нет проверок, нет удаления существующего массива, что ведёт к засорению памяти
  301.     rem Используется при load
  302.     ) else if /I "!__1!"=="load_unsafe" (
  303.        
  304.         set __i=0
  305.         rem Вносим каждую строку файла в массив
  306.         for /f "tokens=*" %%i in (!__3!) do (
  307.             set array_!__2!_!__i!=%%i
  308.             set /a __i+=1
  309.         )
  310.         set array_!__2!_count=!__i!
  311.        
  312.  
  313.     rem == count ==
  314.     rem Количество элементов в массиве
  315.     rem call :array count имя_массива [имя_целевой_переменной=_l]
  316.     ) else if /I "!__1!"=="count" (
  317.    
  318.    
  319.         rem Имя массива
  320.         if "!__2!"=="" (
  321.             echo Не указано имя массива
  322.             goto :eof
  323.         )
  324.        
  325.        
  326.         rem Проверка существования массива
  327.         call :array_notdefined !__2! __errors
  328.        
  329.         rem Если есть ошибки, то выходим
  330.         if not !__errors!==0 goto :eof
  331.        
  332.         set __name=array_!__2!
  333.        
  334.         rem Имя целевой переменной
  335.         set __var=_l
  336.         if not "!__3!"=="" (
  337.             set __var=!__3!
  338.         )
  339.        
  340.         rem Записываем в целевую
  341.         call :set !__var! !__name!_count
  342.        
  343.     rem == dump ==
  344.     rem Вывод массива на экран
  345.     rem call :array dump имя_массива
  346.     ) else if /I "!__1!"=="dump" (
  347.    
  348.         rem Имя массива
  349.         if "!__2!"=="" (
  350.             echo Не указано имя массива
  351.             goto :eof
  352.         )
  353.        
  354.        
  355.         rem Проверка существования массива
  356.         call :array_notdefined !__2! __errors
  357.        
  358.         rem Если есть ошибки, то выходим
  359.         if not !__errors!==0 goto :eof
  360.        
  361.         set __name=array_!__2!
  362.        
  363.         rem Получаем размер
  364.         call :set __count !__name!_count
  365.         set /a __maxindex=!__count!-1
  366.        
  367.         echo array[!__count!]: !__2!
  368.         if !__count!==0 (
  369.             echo Массив не содержит элементов
  370.             goto :eof
  371.         )
  372.        
  373.         for /l %%i in (0,1,!__maxindex!) do (
  374.             call :set __value !__name!_%%i
  375.             echo [%%i] !__value!
  376.         )
  377.  
  378.        
  379.    
  380.     rem == set ==
  381.     rem Присвоение значения элементу
  382.     rem call :array set имя_массива индекс значение
  383.     ) else if /I "!__1!"=="set" (
  384.        
  385.         if "!__4!"=="" (
  386.             echo Не указано значение. Значение не может быть пустым
  387.             goto :eof
  388.         )
  389.         rem Сохраняем параметры, для того, чтобы после вызова get они не потерялись
  390.         set _name=array_!__2!
  391.         set /a _i=!__3!
  392.         set _value=!__4!
  393.            
  394.         rem Получение значения обеспечивает нам проверку параметров
  395.         rem Важно. После операции все локальные переменные (__*) очищаются
  396.         call :array get !__2! !__3! _localresult
  397.        
  398.  
  399.         rem Если результат get существует, то удаляем элемент
  400.         rem Сообщения об ошибках в противном случае покажет сам get
  401.         if defined _localresult (
  402.             set !_name!_!_i!=!_value!
  403.         )
  404.        
  405.         set _localresult=
  406.         set _name=
  407.         set _i=
  408.         set _value=
  409.        
  410.    
  411.     rem == delete ==
  412.     rem Удаление массива
  413.     rem call :array delete имя_массива
  414.     ) else if /I "!__1!"=="delete" (
  415.    
  416.         rem Имя массива
  417.         if "!__2!"=="" (
  418.             echo Не указано имя массива
  419.             goto :eof
  420.         )
  421.        
  422.        
  423.         rem Проверка существования массива
  424.         call :array_notdefined !__2! __errors
  425.        
  426.         rem Если есть ошибки, то выходим
  427.         if not !__errors!==0 goto :eof
  428.        
  429.         set __name=array_!__2!
  430.        
  431.         rem Получаем размер
  432.         call :set __count !__name!_count
  433.         set /a __maxindex=__count-1
  434.        
  435.         rem Удаляем все элементы
  436.         for /l %%i in (0,1,!__maxindex!) do set !__name!_%%i=
  437.         rem Удаляем размер
  438.         set !__name!_count=
  439.                
  440.     rem == del ==
  441.     rem Удаление элемента, элементов или всего массива
  442.     rem call :array del имя_массива [индекс_элемента|набор элементов=удаление всего массива]
  443.     rem Примеры: call :array del myArr "4,6,8"  -  удаляет из массива myArr элементы с индексами 4, 6 и 8
  444.     rem             call :array del myArr 9  -  удаляет из массива myArr 9й элемент
  445.     rem             call :array del myArr   -   удаляет массив myArr
  446.     ) else if /I "!__1!"=="del" (
  447.    
  448.         rem Если не указан индекс, то удаляем весь массив     
  449.         if "!__3!"=="" (
  450.             call :array delete !__2!
  451.             goto :eof
  452.         )
  453.        
  454.         rem Если параметр не число, то перенаправляем на удаление по списку индексов
  455.         set __localresult=
  456.         call :is_number "!__3!" __localresult
  457.         if !__localresult!==0 (
  458.             call :array del_elements !__2! "!__3!"
  459.             goto :eof
  460.         )
  461.        
  462.        
  463.         rem Если индекс указан, то удаляем только элемент
  464.        
  465.         rem Сохраняем параметры, для того, чтобы после вызова get они не потерялись
  466.         set _name=array_!__2!
  467.         set /a _i=!__3!
  468.            
  469.         rem Получение значения обеспечивает нам проверку параметров
  470.         rem Важно. После операции все локальные переменные (__*) очищаются
  471.         set _localresult=
  472.         call :array get !__2! !__3! _localresult
  473.         rem Если результат get не существует, то выходим
  474.         rem Сообщения об ошибках в этом случае покажет сам get
  475.         if not defined _localresult (
  476.             set _name=
  477.             goto :eof
  478.         )
  479.         set _localresult=
  480.  
  481.        
  482.         rem Получаем размер
  483.         call :set __count !_name!_count
  484.         rem maxindex=count-2, так как идём до предпоследнего элемента
  485.         set /a __maxindex=__count-2
  486.         set /a __nextindex=!_i!
  487.  
  488.         rem Пересчёт индексов
  489.         for /l %%i in (!_i!,1,!__maxindex!) do (
  490.             set /a __nextindex+=1
  491.             call :set !_name!_%%i !_name!_!__nextindex!
  492.         )
  493.        
  494.         set /a !_name!_count-=1
  495.        
  496.         rem Удаление последнего элемента (он был перемещёт на позицию вверх)
  497.         set !_name!_!__nextindex!=
  498.        
  499.         rem Удаляем локальные переменные
  500.         set _name=
  501.         set _i=
  502.    
  503.  
  504.     rem == del_elements ==
  505.     rem Удаление элементов по списку индексов
  506.     rem call :array del_elements имя_массива
  507.     rem Лучше использовать del
  508.     ) else if /I "!__1!"=="del_elements" (
  509.    
  510.         rem Имя массива
  511.         if "!__2!"=="" (
  512.             echo Не указано имя массива
  513.             goto :eof
  514.         )
  515.        
  516.        
  517.         rem Проверка существования массива
  518.         call :array_notdefined !__2! __errors
  519.        
  520.         rem Если есть ошибки, то выходим
  521.         if not !__errors!==0 goto :eof
  522.  
  523.         rem Проверка индексов
  524.         if "!__3!"=="" (
  525.             echo Не указан набор индексов
  526.             goto :eof
  527.         )
  528.        
  529.         rem Имя массива с префиксом
  530.         set __name=array_!__2!
  531.    
  532.    
  533.         rem Приводим набор к цисловому набору вида ;54;2;3;5;
  534.         call :to_intset "!__3!" __indexes
  535.  
  536.         rem Получаем размер
  537.         call :set __count !__name!_count
  538.         set /a __maxindex=__count-1
  539.        
  540.         rem Количество удаленных элементов
  541.         rem Используется для поправки размера, и, главное, для смещения индексов
  542.         set /a __deleted=0
  543.        
  544.         rem Пересчёт индексов
  545.         rem Идея состоит в том, что мы бежим по исходному массиву, и если попадаем в позицию
  546.         rem которую нужно удалить, то в текущую позицию помещаем элемент, который будет идти
  547.         set __exit_i_loop=0
  548.         for /l %%i in (0,1,!__maxindex!) do (
  549.             if not !__exit_i_loop!==1 (
  550.  
  551.                 rem Индекс элемента в исходном массиве, соответствущий данному положению
  552.                 set /a __newindex=%%i+!__deleted!
  553.                 set __exit_j_loop=0
  554.                
  555.                 rem Пробегаемся по индексам вперёд, пока будут попадаться индексы элементов
  556.                 rem которых требуется удалить.
  557.                 for /l %%j in (!__newindex!,1,!__maxindex!) do (
  558.                     if not !__exit_j_loop!==1 (
  559.                    
  560.                         rem Если в наборе индексов к удалению содержится текущий, то
  561.                         rem он подлежит удалению, а значит индексы в результирующем массиве
  562.                         rem далее будут отставать от соответствующих в исходном на ещё одну позицию больше
  563.                         call :str_contains __indexes %%j __localresult
  564.                         if !__localresult!==1 (
  565.                             set /a __deleted+=1
  566.                         ) else (
  567.                             set __exit_j_loop=1
  568.                         )
  569.                        
  570.                     )
  571.                    
  572.                                
  573.                 )
  574.                
  575.                 rem Пересчитываем, чтобы понять, нужно ли дальше бежать, или нет
  576.                 set /a __newindex=%%i+!__deleted!
  577.                 if !__newindex! GTR !__maxindex! (
  578.                     set __exit_i_loop=1
  579.                 ) else (
  580.                     call :set !__name!_%%i !__name!_!__newindex!
  581.                 )
  582.            
  583.             )
  584.         )
  585.        
  586.         set /a !__name!_count=!__count!-!__deleted!
  587.        
  588.         rem Удаление последнего элемента (он был перемещёт на позицию вверх)
  589.         set !_name!_!__nextindex!=
  590.        
  591.     rem == add ==
  592.     rem Добавить элемент в конец массива или набор элементов
  593.     rem call :array add имя_массива значение
  594.     rem call :array add имя_массива набор !
  595.     rem Чтобы добавить набор, необходимо указать параметр !
  596.     rem Можно использовать вместо последней конструкции вызов процедуры expand
  597.     ) else if /I "!__1!"=="add" (
  598.        
  599.         rem Имя массива
  600.         if "!__2!"=="" (
  601.             echo Не указано имя массива
  602.             goto :eof
  603.         )
  604.        
  605.         rem Значение
  606.         if "!__3!"=="" (
  607.             echo Не задано значение. Значение не может быть пустым
  608.             goto :eof
  609.         )
  610.        
  611.         rem Пареметр l указывает на то, что добавляется набор
  612.         if /i "!__4!"=="!" (
  613.             call :array expand !__2! "!__3!"
  614.             goto :eof
  615.         )
  616.                        
  617.         rem Проверка существования массива
  618.         call :array_notdefined !__2! __errors
  619.        
  620.         rem Если есть ошибки, то выходим
  621.         if not !__errors!==0 goto :eof
  622.        
  623.         rem Имя массива с префиксом
  624.         set __name=array_!__2!
  625.        
  626.         rem Получаем размер
  627.         call :set __count !__name!_count
  628.         rem Задаём значение
  629.         set !__name!_!__count!=!__3!
  630.         rem и увеличиваем размер
  631.         set /a !__name!_count+=1
  632.        
  633.        
  634.     rem == expand ==
  635.     rem Добавить набор элементов в конец массива
  636.     rem call :array expand имя_массива набор элементов
  637.     rem Пример:       call :array expand myArr "'first line' 'Вторая строка' 12 54"
  638.     rem     добавление к массиву myArr 4х элементов
  639.     ) else if /I "!__1!"=="expand" (
  640.    
  641.         rem Имя массива
  642.         if "!__2!"=="" (
  643.             echo Не указано имя массива
  644.             goto :eof
  645.         )
  646.        
  647.         rem Набор
  648.         if "!__3!"=="" (
  649.             echo Не указан набор элементов. Набор не может быть пустым
  650.             goto :eof
  651.         )
  652.        
  653.         rem Проверка существования массива
  654.         call :array_notdefined !__2! __errors
  655.        
  656.         rem Если есть ошибки, то выходим
  657.         if not !__errors!==0 goto :eof
  658.        
  659.         rem Имя массива с префиксом
  660.         set __name=array_!__2!
  661.        
  662.         rem Получаем размер
  663.         call :set __count !__name!_count
  664.        
  665.         rem Заменяем одинарные кавычки на двойные
  666.         set __3=!__3:'="!
  667.        
  668.         rem Создаем последовательно каждый элемент и присваиваем значение, начиная с последнего
  669.         set /a __i=!__count!
  670.         for %%i in (!__3!) do (
  671.             rem ~ - убираем кавычки, которые необходимы для группировки
  672.             set !__name!_!__i!=%%~i
  673.             set /a __i+=1
  674.         )
  675.         set /a !__name!_count=!__i!
  676.        
  677.        
  678.     rem == copy ==
  679.     rem Копирование массива
  680.     rem call :array copy имя_копируемого имя_конечного
  681.     ) else if /I "!__1!"=="copy" (
  682.        
  683.         rem Имя исходного массива
  684.         if "!__2!"=="" (
  685.             echo Не указано имя исходного массива
  686.             goto :eof
  687.         )
  688.        
  689.         rem Имя целевого массива
  690.         if "!__3!"=="" (
  691.             echo Не указано имя целевого массива
  692.             goto :eof
  693.         )
  694.        
  695.         rem Проверка существования массива
  696.         call :array_notdefined !__2! __errors
  697.        
  698.         rem Если есть ошибки, то выходим
  699.         if not !__errors!==0 goto :eof
  700.        
  701.        
  702.         rem Имена массивов с префиксом
  703.         set _name=array_!__2!
  704.         set _name_new=array_!__3!
  705.        
  706.         rem Получаем размер
  707.         call :set _count !_name!_count
  708.         set /a _maxindex = !_count!-1
  709.        
  710.         rem Удаляем целевой массив, если существует
  711.         call :array_del_ifdef !__3!
  712.  
  713.        
  714.         rem Копируем поэлементно
  715.         for /l %%i in (0,1,!_maxindex!) do (
  716.             call :set !_name_new!_%%i !_name!_%%i
  717.         )
  718.        
  719.         rem Копируем размер
  720.         set /a !_name_new!_count=!_count!
  721.    
  722.         rem Удаляем локальные переменные
  723.         set _name=
  724.         set _name_new=
  725.         set _count=
  726.         set _maxindex=
  727.        
  728.     rem == each ==
  729.     rem Вызов комманды для каждого элемента массива
  730.     rem В качество подстановок используйте:
  731.     rem     При вызове комманды:
  732.     rem         _i_ - индекс текущего элемента
  733.     rem         _val_ - значение текущего элемента
  734.     rem         call :array each имя_массива комманда x
  735.     rem
  736.     rem         Пример:
  737.     rem             call :array new B "1 4 1 6 6 2"
  738.     rem             set sum=0
  739.     rem             call :array each B "set /a sum+=_val_" x
  740.     rem             echo !sum!
  741.     rem         Выведет 20 - сумма всех элементов в массива
  742.     rem     При вызове процедуры:
  743.     rem         %~1 - значение (~ - убираем кавычки)
  744.     rem         %2  - номер индекса
  745.     rem
  746.     rem         Пример:
  747.     rem             call :array new B "1 4 1 6 6 2"
  748.     rem             call :array each B to_string
  749.     rem             echo !str!
  750.     rem             :to_string
  751.     rem                 set str=!str!%~1
  752.     rem             goto :eof
  753.     rem         Выведет 141662
  754.    
  755.     ) else if /I "!__1!"=="each" (
  756.    
  757.         rem Имя массива
  758.         if "!__2!"=="" (
  759.             echo Не указано имя исходного массива
  760.             goto :eof
  761.         )
  762.    
  763.         rem Проверка существования массива
  764.         call :array_notdefined !__2! __errors
  765.        
  766.         rem Если есть ошибки, то выходим
  767.         if not !__errors!==0 goto :eof
  768.        
  769.        
  770.         rem Комманда
  771.         if "!__3!"=="" (
  772.             echo Не задана камманда each
  773.             goto :eof
  774.         )
  775.        
  776.         set __is_command=0
  777.         if /i "!__4!"=="x" (
  778.             set __is_command=1
  779.         )
  780.        
  781.         set __command=!__3!
  782.        
  783.         rem Имя массива с префиксом
  784.         set __name=array_!__2!
  785.        
  786.         rem Получаем размер
  787.         call :set __count !__name!_count
  788.         set /a __maxindex = !__count!-1
  789.        
  790.         for /l %%i in (0,1,!__maxindex!) do (
  791.             call :set _val_ !__name!_%%i
  792.            
  793.             if !__is_command!==1 (
  794.                 call :str_replace __command _i_ %%i __exec
  795.                 call :str_replace __exec _val_ "!_val_!"
  796.                 !__exec!
  797.             ) else (
  798.                 call :!__command! "!_val_!" %%i
  799.             )
  800.            
  801.         )
  802.        
  803.        
  804.     rem == sort ==
  805.     rem Сортировка массива
  806.     rem Укажите параметр R для сортировки в обратном порядке
  807.     rem call :array sort имя_массива
  808.     rem call :array sort имя_массива R   - сортировка в обратном порядке
  809.     ) else if /I "!__1!"=="sort" (
  810.    
  811.         rem Имя массива
  812.         if "!__2!"=="" (
  813.             echo Не указано имя исходного массива
  814.             goto :eof
  815.         )
  816.    
  817.         rem Проверка существования массива
  818.         call :array_notdefined !__2! __errors
  819.        
  820.         rem Если есть ошибки, то выходим
  821.         if not !__errors!==0 goto :eof
  822.        
  823.        
  824.         rem Реверсивная сортировка
  825.         if /I "!__3!"=="R" (
  826.             set _rev=/r
  827.         )
  828.        
  829.        
  830.         set _shortname=!__2!
  831.         rem Имя массива с префиксом
  832.         set _name=array_!__2!
  833.        
  834.         rem Генерируем имя для временного файла
  835.         set _tmpfile=%TMP%\array_sort_%random%%random%
  836.  
  837.         rem Сохраняем массив в файл
  838.         call :array list !_shortname! > "!_tmpfile!.txt"
  839.        
  840.         rem Сортируем из файла
  841.         sort !_rev! !_tmpfile!.txt /o "!_tmpfile!_sorted.txt"
  842.        
  843.         rem Удаляем текущиий массив - можно не удалять, потому что размер останется таким же
  844.         rem и все переменные просто перезапишутся
  845.         rem call :array delete !_shortname!
  846.        
  847.         rem Читаем результат из файла
  848.         call :array load_unsafe !_shortname! "!_tmpfile!_sorted.txt"
  849.        
  850.         rem Удаляем временные файлы
  851.         del /f /q "!_tmpfile!_sorted.txt" "!_tmpfile!.txt"
  852.        
  853.        
  854.         rem Удаляем локальные переменные
  855.         set _name=
  856.         set _tmpfile=
  857.         set _shortname=
  858.         set _rev=
  859.        
  860.        
  861.     rem == find ==
  862.     rem Поиск элемента
  863.     rem Возвращает номер первого найденного элемента или -1, если не найдено
  864.     rem Используёте параметр I для игнорирования регистра
  865.     rem call :array find имя_массива искомый_элемент N [имя_целевой_переменной=_l] - N - лобой символ, отличный от i
  866.     rem call :array find имя_массива искомый_элемент I [имя_целевой_переменной=_l]  - поиск с игнорированием регистра
  867.     rem Пример: call :array find myArr "Себастьян Перейро" N sebastNum
  868.     rem возвращает в переменную sebastNum номер элемента в массиве myArr, содержащий строку Себастьян Перейро с учётом регистра
  869.     rem N - любой символ, кроме I, чтобы не включить игнорирование регистра
  870.     ) else if /i "!__1!"=="find" (
  871.    
  872.         rem Имя массива
  873.         if "!__2!"=="" (
  874.             echo Не указано имя исходного массива
  875.             goto :eof
  876.         )
  877.    
  878.         rem Проверка существования массива
  879.         call :array_notdefined !__2! __errors
  880.        
  881.         rem Если есть ошибки, то выходим
  882.         if not !__errors!==0 goto :eof
  883.        
  884.         rem Значение
  885.         if "!__3!"=="" (
  886.             echo Не задано значение. Значение не может быть пустым
  887.             goto :eof
  888.         )
  889.         set __find=!__3!
  890.        
  891.         rem Имя массива с префиксом
  892.         set __name=array_!__2!
  893.        
  894.         rem Игнорирование регистра
  895.         if /i "!__4!"=="I" (
  896.             set __ignorecase=1
  897.         )
  898.        
  899.         rem Имя целевой переменной
  900.         set __var=_l
  901.         if not "!__5!"=="" (
  902.             set __var=!__5!
  903.         )
  904.        
  905.         rem Получаем размер
  906.         call :set __count !__name!_count
  907.         set /a __maxindex=__count-1
  908.        
  909.         rem Устанавливаем результат -1
  910.         set !__var!=-1
  911.        
  912.         set __exit_loop=0
  913.         for /l %%i in (0,1,!__maxindex!) do (
  914.             if not !__exit_loop!==1 (
  915.                 rem Читаем значение элемента
  916.                 call :set __value !__name!_%%i
  917.                 rem Сравниваем со строкой поиска с ignorecase
  918.                 rem Постановка флага как переменной вызывает ошибку
  919.                 if !__ignorecase!==1 if /i "!__value!"=="!__find!" (
  920.                         set __exit_loop=1
  921.                         set !__var!=%%i
  922.                 )
  923.                
  924.                 if not !__ignorecase!==1 if "!__value!"=="!__find!" (
  925.                         set __exit_loop=1
  926.                         set !__var!=%%i
  927.                 )
  928.             )
  929.         )
  930.        
  931.        
  932.     )
  933.     call :clear_local
  934.  
  935. goto :eof
  936.  
  937.  
  938.  
  939. rem Копирует значение одной переменной в другую
  940. rem Плюс в том, что имя переменной, значение которой извлекается, может быть составным
  941. rem call :set имя_целевой_переменной имя_переменной_содержищее_значение
  942. :set
  943.     set %~1=!%~2!
  944. goto :eof
  945.  
  946. rem Удаление локальных переменных (начинаются с __)
  947. :clear_local
  948.     rem Устанавливаю переменную __, чтобы set __ не возвращал "Переменная среды __ не определена"
  949.     set __=0
  950.     for /F "usebackq delims==" %%i in (`set __`) do set %%i=
  951. goto :eof
  952.  
  953.  
  954. :array_del_ifdef
  955.     call :array_notdefined %1 __array_del_ifdef_result H
  956.     if !__array_del_ifdef_result!==0 call :array delete %1
  957. goto :eof
  958.  
  959. rem Проверка существования массива
  960. :array_notdefined
  961.     rem Устанавливаем имя целевой переменной
  962.     set __var=_l
  963.    
  964.     rem Тихая проверка - не выводить сообщение
  965.     set __hide=0
  966.    
  967.     if not "%2"=="" (
  968.         set __var=%2
  969.     )
  970.    
  971.     if /i "%3"=="h" (
  972.         set __hide=1
  973.     )
  974.    
  975.     if not defined !__var! set /a !__var!=0
  976.    
  977.     rem Проверка существования переменной, содержащей размер
  978.     if not defined array_%~1_count (
  979.         if not !__hide!==1 echo Массив %~1 не определен
  980.         set /a !__var!+=1
  981.     )
  982.    
  983. goto :eof
  984.  
  985. rem Перевод набора индексов к виду ;1;62;2;5;6;
  986. rem чтобы можно было выполнять проверку наличия числа: ;%i%;
  987. rem call :to_intset набор [имя_целевой_переменной=_l]
  988. rem Пример:
  989. rem call :to_intset "1 4 76 , 56, 34 ,6" set
  990. rem echo %set%
  991. rem выведет: ;1;4;76;56;34;6;
  992. :to_intset
  993.     rem Устанавливаем имя целевой переменной
  994.     set __var=_l
  995.    
  996.     if not "%2"=="" (
  997.         set __var=%2
  998.     )
  999.    
  1000.     rem Добавляем елементы набора к строке
  1001.     set __intset=
  1002.     for %%i in (%~1) do (
  1003.             set __intset=!__intset!;%%i
  1004.     )
  1005.    
  1006.     rem Закрывающая ;
  1007.     set __intset=!__intset!;
  1008.    
  1009.     rem Записываем результат
  1010.     call :set !__var! __intset
  1011.    
  1012.     set __intset=
  1013.    
  1014. goto :eof
  1015.  
  1016.  
  1017. rem Является ли значение(!) числом
  1018. rem call :is_number значение [имя_целевой_переменной=_l]
  1019. :is_number
  1020.     rem Устанавливаем имя целевой переменной
  1021.     set _var=_l
  1022.    
  1023.     if not "%2"=="" (
  1024.         set _var=%2
  1025.     )
  1026.    
  1027.     set _val=%~1
  1028.     set _newval=%~1
  1029.     rem Выход из цикла, а заодно и индикатор, потому что
  1030.     rem Если из цикла был совершён вынужденный выход, то значит число
  1031.     set _exit_loop_local=0
  1032.  
  1033.     rem Трюк в том, чтобы вырезать все цифры, и если останется пустая строка, то значит было число
  1034.     rem Подобную реализацию видел на каком-то сайте, посвящённом быдлокодерам, но вот здесь пригодилось
  1035.     for /l %%i in (0,1,9) do (
  1036.         if not !_exit_loop_local!==1 (
  1037.             rem Новое имя с новой подстановкой текущей цифры
  1038.             set _newname="_newval:%%i="
  1039.             call :set _newval !_newname!
  1040.            
  1041.             if "!_newval!"=="" (
  1042.                 set _exit_loop_local=1
  1043.             )
  1044.         )
  1045.     )
  1046.    
  1047.     rem Записываем результат
  1048.     set !_var!=!_exit_loop_local!
  1049.    
  1050.     set _var=
  1051.     set _exit_loop_local=
  1052.     set _val=
  1053.     set _newval=
  1054.     set _newname=
  1055.     set _name=
  1056.        
  1057. goto :eof
  1058. rem Есть путь быстрее, но в случае передачи строки выводится сообщение об ошибке,
  1059. rem которое никак не перехватить, однако определение всё же происходит
  1060. rem set __tmp=
  1061. rem set /a __tmp=%1
  1062. rem if not defined __tmp (
  1063. rem     echo string
  1064. rem ) else (
  1065. rem     echo number
  1066. rem )
  1067.  
  1068.  
  1069.  
  1070. rem Замена подстроки
  1071. rem call :str_replace имя_исходной_переменной искомая_строка подстановка [имя_целевой_переменной=имя_исходной_переменной]
  1072. rem set str=Привет, Маша. Как дела?
  1073. rem call :str_replace str "как дела" "Как настроение" str2
  1074. rem echo !str2!
  1075. rem Результат: Привет, Маша. Как настроение?
  1076. :str_replace
  1077.     rem Устанавливаем имена целевой и исходной переменных
  1078.     set _var=%1
  1079.     set _result=%1
  1080.    
  1081.     rem Искомая строка
  1082.     set _from=%~2
  1083.     rem Строка подстановка
  1084.     set _to=%~3
  1085.    
  1086.     if not "%4"=="" (
  1087.         set _result=%4
  1088.     )
  1089.    
  1090.     set _newvarname=!_var!:!_from!=!_to!
  1091.     call :set !_result! "!_newvarname!"
  1092.    
  1093.     set _var=
  1094.     set _result=
  1095.     set _from=
  1096.     set _to=
  1097.     set _newvarname=
  1098. goto :eof
  1099.  
  1100. rem Проверка наличия цисла в наборе
  1101. rem Набор должен иметь вид ;3;645;12;56;7;0;
  1102. rem В целевой переменной будет 1 в случае успеха, и 0 в противном случае
  1103. rem call :str_contains имя_переменной_с_набором число [целевая_переменная=_el]
  1104. :str_contains
  1105.     rem Устанавливаем имя целевой переменной
  1106.     set _var=_l
  1107.    
  1108.     if not "%3"=="" (
  1109.         set _var=%3
  1110.     )
  1111.    
  1112.    
  1113.     rem Новое имя переменной с подстановкой. имя_переменной:;число;=#
  1114.     rem таким образом заменяем число, окруженное ; на решётку
  1115.     set _newstr=%1:;%2;=#
  1116.    
  1117.     call :set _newstr "!_newstr!"
  1118.  
  1119.     rem Если число присутствует, то новое значение не совпадёт состарым,
  1120.     rem т.к. в новом искомое число будет заменено на решётку
  1121.     if not "!_newstr!"=="!%1!" (
  1122.         set !_var!=1
  1123.     ) else (
  1124.         set !_var!=0
  1125.     )
  1126.    
  1127.     set _var=
  1128.     set _newstr=
  1129. goto :eof
  1130.  
  1131. :exit
  1132. ENDLOCAL
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement