PDA

Показать полную графическую версию : [решено] Обработка ключей запуска CMD- файла


Страниц : [1] 2

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

Я сделал как мог, дабы не усложнять скрипт и себе жизнь. Но может кто подскажет чего ? :)

Iska
10-12-2009, 04:19
Как раз так будет заметное усложнение логики. Наиболее просто реализуется вариант с парами ключ/значение:
@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
устроит

amel27
10-12-2009, 06:01
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

amel27
10-12-2009, 16:07
volk1234, один параметр - одна процедура. FOR перебирает все и вызывает их по очереди

volk1234
10-12-2009, 21:36
Тоесть можно сделать переключатель первый -do(-l -un) как я и сделал, а потом можно сделать перебор циклом ?

-do reg1 reg2 mountp

Drongo
10-12-2009, 23:45
Тоесть можно сделать переключатель первый »Нет, вместо ключа -do [опция]. Написать один ключ, который будет что-то выполнять.
Вместо
-do reg1
-do reg2
написать так
doreg1
doreg2 и выполнять нужный в зависимости от выбора, ведь опция -do пустая, сама по себе не делает никаких действий?

volk1234
11-12-2009, 10:54
Как то непривычно, старался сделать как в других программках.
Вспомнил - просто не знал как реализовать в принципе обработку ключей - поэтому решил ограничится 2 уровнями -
на первом ключи одноуровневые - где переход осуществляется сразу,
-ms, -full,-unlockall.
А также ключи
-do -l -un
при обработки которых переход осуществлялся во вторую функцию(метку) где и обрабатывался второй ключ.

Пока не совсем предщставляю как реализовать например обработку

doreg1 255

amel27
11-12-2009, 12:36
не совсем предщставляю как реализовать например обработку »
например, так:

@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

Drongo
11-12-2009, 13:25
doreg1 255 »У меня в GUI, команда формируется так
-do_reg1_223Но потом в процессе обработки символы подчёркивания заменяются на пробелы. И на выходе мы видим
nmar.cmd -do reg1 223

NiOl
11-12-2009, 15:25
А мне нравится 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
?

amel27
13-12-2009, 15:11
Строка
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 ключей ?

amel27
15-12-2009, 03:26
Для них отдельные строки писать, или оставить прямую обработку »

главное, чтобы соблюдалось строгое однозначное соответствие ключ --> процедура, а префикс для определения где ключ, а где его параметр можно задать какой угодно: "do", "-" или что угодно

volk1234
17-12-2009, 01:22
Привет еще раз :)
Все бы хорошо, да я запутался с отсечением знака '-' от имени ключа. Белиберда какая то получается. Как правильно отсечь минус от имени ключа? В самом скрипте поменял строку

If /I "%$P:~0,2%"=="-" Set /A $I=%$I%+1

тоесть я знаю надо применить :~1, но не знаю где...
А еще как сделать, чтобы проверялись следующие условия-
ключ -unlockall должен выполнятся всегда первым или только он один
ключи -l* и -un* одновременно выполнятся не должны

Iska
17-12-2009, 04:10
Можно так (удалит все вхождения «-»):
set key=-ms
set skey=%key:-=%
echo [%key%], [%skey%]

volk1234
17-12-2009, 10:20
Это не универсально, тогда меня и моя процедура перехода устроит -

If "Key1" = "-ms" goto ***
If "Key1" = "-full" goto ***

amel27
17-12-2009, 10:40
Все бы хорошо, да я запутался с отсечением знака '-' от имени ключа. Белиберда какая то получается. Как правильно отсечь минус от имени ключа? »
не совсем понял о чем речь, поэтому старый пример для ключей "-":

@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