Показать полную графическую версию : [решено] Обработка ключей запуска CMD- файла
volk1234
10-12-2009, 00:34
Привет гуру (или гурам?)! В общем привет!
Сделал я такой скриптик - http://forum.oszone.net/thread-141480.html
Даже GUI ваяем. Встал вопрос о ключах для командной строки.
У меня они организованны убого - по одному ключу (ну еще + 1 опцию) за раз обрабатывается.
Вот код:
Set Key1=%1
Set Key2=%2
.....
:CORE1
If "%Key1%" == "-full" Goto :full
If "%Key1%" == "-nomore" Goto :nomore
If "%Key1%" == "-kb" Goto :kbinstall
If "%Key1%" == "-p" Goto :pusb
If "%Key1%" == "-pd" Goto :pdisk
If "%Key1%" == "-pall" Goto :pall
If "%Key1%" == "-ms" Goto :ms
If "%Key1%" == "-unlockall" Goto :unlockall
If "%Key1%" == "-do" Goto :CORE_do
If "%Key1%" == "-l" Goto :CORE_l
If "%Key1%" == "-un" Goto :CORE_u
If "%Key1%" == "-help" Goto :Syntax
Goto :Syntax_Error
:CORE_do
If "%Key2%" == "" Goto :Syntax_Error
If "%Key2%" == "reg1" Goto :reg1
If "%Key2%" == "reg2" Goto :reg2
If "%Key2%" == "srvoff" Goto :srvoff
If "%Key2%" == "srvon" Goto :srvon
If "%Key2%" == "mountp" Goto :mountp
Goto :Syntax_Error
:CORE_l
Call :subinacl_DETECT
If "%Key2%" == "" Goto :Syntax_Error
If "%Key2%" == "reg1" Goto :lockreg1
If "%Key2%" == "reg2" Goto :lockreg2
If "%Key2%" == "usbadd" Goto :lockusbadd
If "%Key2%" == "usbuse" Goto :lockusbuse
If "%Key2%" == "usbwrite" Goto :lockusbwrite
If "%Key2%" == "mountp" Goto :lockmountp
Goto :Syntax_Error
:CORE_u
Call :subinacl_DETECT
If "%Key2%" == "" Goto :Syntax_Error
If "%Key2%" == "reg1" Goto :unreg1
If "%Key2%" == "reg2" Goto :unreg2
If "%Key2%" == "usbadd" Goto :unusbadd
If "%Key2%" == "usbuse" Goto :unusbuse
If "%Key2%" == "usbwrite" Goto :unusbwrite
If "%Key2%" == "mountp" Goto :unmountp
Goto :Syntax_Error
.....
:reg1
If Not "%Key3%"=="" Set NDTAR=%Key3%
....
То есть, чтобы выполнить 2 команды надо 2 раза запустить скрипт
nmar -do reg1
nmar -do reg2
А конечно охота сразу все указывать
nmar -do reg1 reg2 montp
Я сделал как мог, дабы не усложнять скрипт и себе жизнь. Но может кто подскажет чего ? :)
Как раз так будет заметное усложнение логики. Наиболее просто реализуется вариант с парами ключ/значение:
@echo off
setlocal enableextensions enabledelayedexpansion
:Next
Set Key1=%~1
Set Key2=%~2
echo.Key1:[%Key1%] Key2:[%Key2%]
if defined Key1 (
if defined Key2 (
if [%Key1%] equ [-do] call :SomeProcDO "%Key2%"
if [%Key1%] equ [-kb] call :SomeProcKB "%Key2%"
shift
shift
goto :Next
)
)
endlocal
exit /b 0
:SomeProcDO
echo SomeProcDO: %~1
exit /b /0
:SomeProcKB
echo SomeProcKB: %~1
exit /b /0
Пример вызова: 0005.cmd -do 1111 -do 2222 -kb 3333
Key1:[-do] Key2:[1111]
SomeProcDO: 1111
Key1:[-do] Key2:[2222]
SomeProcDO: 2222
Key1:[-kb] Key2:[3333]
SomeProcKB: 3333
Key1:[] Key2:[]
Ключи могут повторяться, перемежаться; главное — чтобы не нарушалось правило «на каждый ключ одно значение».
Другой вариант — ещё один ключ, например «-list», задающий имя текстового файла, содержащего те же самые пары «ключ/значение», например, в виде:
Some List.txt
; Some comment 1
do=4444
kb=5555
; Some comment 2
do=6666
При нахождении данного ключа в командной строке пакетного файла вызывается процедура его разбора посредством «for /f» и далее делается либо то же самое сравнение, что в предыдущем примере, либо пакетный файл вызывает самого себя, передавая аргументами пару «ключ/значение», заданные в очередной строке текстового файла, наподобие:
@echo off
setlocal enableextensions enabledelayedexpansion
:Next
Set Key1=%~1
Set Key2=%~2
echo.Key1:[%Key1%] Key2:[%Key2%]
if defined Key1 (
if defined Key2 (
if [%Key1%] equ [-list] call :ParseList "%Key2%"
if [%Key1%] equ [-do] call :SomeProcDO "%Key2%"
if [%Key1%] equ [-kb] call :SomeProcKB "%Key2%"
shift
shift
goto :Next
)
)
endlocal
exit /b 0
:SomeProcDO
echo SomeProcDO: %~1
exit /b /0
:SomeProcKB
echo SomeProcKB: %~1
exit /b /0
:ParseList
setlocal enableextensions enabledelayedexpansion
if exist "%~1" (
for /f "usebackq tokens=1,2 eol=; delims==" %%i in ("%~1") do call "%~dpnx0" -%%i "%%j"
) else (
echo File list [%~1] not found.
)
endlocal
exit /b /0
Пример вызова:0006.cmd -list "C:\Песочница\41\Some List.txt"
Key1:[-list] Key2:[C:\Песочница\41\Some List.txt]
Key1:[-do] Key2:[4444]
SomeProcDO: 4444
Key1:[] Key2:[]
Key1:[-kb] Key2:[5555]
SomeProcKB: 5555
Key1:[] Key2:[]
Key1:[-do] Key2:[6666]
SomeProcDO: 6666
Key1:[] Key2:[]
Key1:[] Key2:[]Усложнённый пример вызова, с перемежением обычных ключей и ключа «-list»:
0006.cmd -do 1111 -do 2222 -list "C:\Песочница\41\Some List.txt" -kb 3333
Key1:[-do] Key2:[1111]
SomeProcDO: 1111
Key1:[-do] Key2:[2222]
SomeProcDO: 2222
Key1:[-list] Key2:[C:\Песочница\41\Some List.txt]
Key1:[-do] Key2:[4444]
SomeProcDO: 4444
Key1:[] Key2:[]
Key1:[-kb] Key2:[5555]
SomeProcKB: 5555
Key1:[] Key2:[]
Key1:[-do] Key2:[6666]
SomeProcDO: 6666
Key1:[] Key2:[]
Key1:[-kb] Key2:[3333]
SomeProcKB: 3333
Key1:[] Key2:[]
volk1234
10-12-2009, 04:26
В принципе даже вариант
nmar -do reg1 -do reg2 -do mountp
устроит
volk1234, не вижу смысла в разборе параметров, которые используются для именования процедур:
nmar do_reg1 do_reg2 do_mountp
For %%i In (%*) Do Call :%%i
чтобы выполнить 2 команды надо 2 раза запустить скрипт »напиши батник... =)
volk1234
10-12-2009, 15:45
amel27
Эмм.. не понял :dont-know
volk1234, один параметр - одна процедура. FOR перебирает все и вызывает их по очереди
volk1234
10-12-2009, 21:36
Тоесть можно сделать переключатель первый -do(-l -un) как я и сделал, а потом можно сделать перебор циклом ?
-do reg1 reg2 mountp
Тоесть можно сделать переключатель первый »Нет, вместо ключа -do [опция]. Написать один ключ, который будет что-то выполнять.
Вместо
-do reg1
-do reg2
написать так
doreg1
doreg2 и выполнять нужный в зависимости от выбора, ведь опция -do пустая, сама по себе не делает никаких действий?
volk1234
11-12-2009, 10:54
Как то непривычно, старался сделать как в других программках.
Вспомнил - просто не знал как реализовать в принципе обработку ключей - поэтому решил ограничится 2 уровнями -
на первом ключи одноуровневые - где переход осуществляется сразу,
-ms, -full,-unlockall.
А также ключи
-do -l -un
при обработки которых переход осуществлялся во вторую функцию(метку) где и обрабатывался второй ключ.
Пока не совсем предщставляю как реализовать например обработку
doreg1 255
не совсем предщставляю как реализовать например обработку »
например, так:
@Echo Off
Set $I=0& For %%i In (%*) Do Set $P=%%i& Call :CMD_PARSE
For /F "Tokens=1* Delims==" %%i In ('Set $_') Do Call :%%j
Exit /B
:DOREG1
Echo DOREG1 %*
GoTo :EOF
:DOREG2
Echo DOREG2 %*
GoTo :EOF
:CMD_PARSE
If /I "%$P:~0,2%"=="do" Set /A $I=%$I%+1
Call Set $_%$I%=%%$_%$I%%%%$P%
GoTo :EOF
test.cmd doreg1 255 doreg2 128 256
doreg1 255 »У меня в GUI, команда формируется так
-do_reg1_223Но потом в процессе обработки символы подчёркивания заменяются на пробелы. И на выходе мы видим
nmar.cmd -do reg1 223
А мне нравится SHIFTом пользоваться, например:
@Echo off
SetLocal EnableExtensions
rem демонстрация обработки ключей.
:Loop
set Key=%1
set Key=%Key:?=h%
shift
rem Недостаток в том, что желательно проверить ключ на совпадение, иначе будет аварийное завершение батника.
GoTo L%Key% 2>nul
Echo Неверный параметр: "%1" (используйте спраку: %~nx0 /? )
:L
exit
:L-H
:L/h
Echo Ключи:
Echo -h - Подсказка
Echo -d ^<mask^> - Каталог
Echo -r - Перезагрузка ;)
Echo -p ^<Start^> ^<Finish^> - Пинг диапазона адресов
Goto Loop
:L/D
:L-D
dir /b /on /a /s %1
shift
Goto Loop
:L/R
:L-R
msg * Bye! ;)
rem Reboot -r -t 1
Goto Loop
:L/P
:L-P
for /L %%a in (%1,1,%2) do ping -a -n 1 192.168.0.%%a
shift & shift
Goto Loop
volk1234
13-12-2009, 12:42
amel27
Строка
For /F "Tokens=1* Delims==" %%i In ('Set $_') Do Call :%%j
Непонятна. :blush:
Создается переменная 1* которая состоит из всех оставшихся ключей ? -
doreg1 255 doreg2 128 256
Delims==" означает что разделители - пробелы и знак равно могут быть?
Что за хитрые переменные $_*
Я понимаю, что они отделяют команды от параметров, но КАК ? :blush: :blush:
И тогда почему Set $_, а не Set $_%%i
?
Строка
For /F "Tokens=1* Delims==" %%i In ('Set $_') Do Call :%%j
Непонятна. »тут как раз все просто - команда "Set $_" выдает список переменных, имя которых начинается на $_, из этого списка выделяются только значения (только то, что находится после знака "="), далее выполняется CALL по каждому такому значению
означает что разделители - пробелы и знак равно могут быть? »нет, только "="
Что за хитрые переменные $_* »
$_1 - содержит имя 1-го параметра (начинается на "do") с подпараметрами (остальные);
$_2 - содержит имя 2-го параметра (начинается на "do") с подпараметрами (остальные);
...
каждая новая переменная $_* создается если параметр начинается на "do", иначе параметр "прибавляется" к последней такой переменной, команда:Call Set $_%$I%=%%$_%$I%%%%$P%
volk1234
15-12-2009, 01:35
Я прошу прощения за паузу - ну просто невозможно попасть за компьютер, настолько много дел перед н.г.
Вопрос следующий - а вот ключи которые у меня просто -
-ms
-unlockall
-full
-nomore
-kb
Для них отдельные строки писать, или оставить прямую обработку через IF "%1"="-ms" Goto
а потом ваш код + обработку -lreg1 ключей и -unreg1 -unreg2 ключей ?
Для них отдельные строки писать, или оставить прямую обработку »
главное, чтобы соблюдалось строгое однозначное соответствие ключ --> процедура, а префикс для определения где ключ, а где его параметр можно задать какой угодно: "do", "-" или что угодно
volk1234
17-12-2009, 01:22
Привет еще раз :)
Все бы хорошо, да я запутался с отсечением знака '-' от имени ключа. Белиберда какая то получается. Как правильно отсечь минус от имени ключа? В самом скрипте поменял строку
If /I "%$P:~0,2%"=="-" Set /A $I=%$I%+1
тоесть я знаю надо применить :~1, но не знаю где...
А еще как сделать, чтобы проверялись следующие условия-
ключ -unlockall должен выполнятся всегда первым или только он один
ключи -l* и -un* одновременно выполнятся не должны
Можно так (удалит все вхождения «-»):
set key=-ms
set skey=%key:-=%
echo [%key%], [%skey%]
volk1234
17-12-2009, 10:20
Это не универсально, тогда меня и моя процедура перехода устроит -
If "Key1" = "-ms" goto ***
If "Key1" = "-full" goto ***
Все бы хорошо, да я запутался с отсечением знака '-' от имени ключа. Белиберда какая то получается. Как правильно отсечь минус от имени ключа? »
не совсем понял о чем речь, поэтому старый пример для ключей "-":
@Echo Off
Set $I=0& For %%i In (%*) Do Set $P=%%i& Call :CMD_PARSE
For /F "Tokens=1* Delims==" %%i In ('Set $_') Do Call :%%j
Exit /B
:REG1
Echo DOREG1 %*
GoTo :EOF
:REG2
Echo DOREG2 %*
GoTo :EOF
:CMD_PARSE
If /I "%$P:~0,1%"=="-" Set $P=%$P:~1%& Set /A $I=%$I%+1
Call Set $_%$I%=%%$_%$I%%%%$P%
GoTo :EOF
test.cmd -reg1 255 -reg2 128 256
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.