Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Обработка ключей запуска CMD- файла (http://forum.oszone.net/showthread.php?t=159734)

volk1234 10-12-2009 00:34 1291122

Обработка ключей запуска CMD- файла
 
Привет гуру (или гурам?)! В общем привет!
Сделал я такой скриптик - 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 1291189

Как раз так будет заметное усложнение логики. Наиболее просто реализуется вариант с парами ключ/значение:
читать дальше »
Код:

@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 1291191

В принципе даже вариант
Код:

nmar -do reg1 -do reg2 -do mountp
устроит

amel27 10-12-2009 06:01 1291209

volk1234, не вижу смысла в разборе параметров, которые используются для именования процедур:
Код:

nmar do_reg1 do_reg2 do_mountp
Код:

For %%i In (%*) Do Call :%%i
Цитата:

Цитата volk1234
чтобы выполнить 2 команды надо 2 раза запустить скрипт »

напиши батник... =)

volk1234 10-12-2009 15:45 1291556

amel27

Эмм.. не понял :dont-know

amel27 10-12-2009 16:07 1291572

volk1234, один параметр - одна процедура. FOR перебирает все и вызывает их по очереди

volk1234 10-12-2009 21:36 1291906

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

Код:

-do reg1 reg2 mountp

Drongo 10-12-2009 23:45 1292009

Цитата:

Цитата volk1234
Тоесть можно сделать переключатель первый »

Нет, вместо ключа -do [опция]. Написать один ключ, который будет что-то выполнять.
Вместо
Код:

-do reg1
-do reg2

написать так
Код:

doreg1
doreg2

и выполнять нужный в зависимости от выбора, ведь опция -do пустая, сама по себе не делает никаких действий?

volk1234 11-12-2009 10:54 1292335

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

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

doreg1 255

amel27 11-12-2009 12:36 1292428

Цитата:

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

например, так:
Код:

@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 1292456

Цитата:

Цитата volk1234
doreg1 255 »

У меня в GUI, команда формируется так
Код:

-do_reg1_223
Но потом в процессе обработки символы подчёркивания заменяются на пробелы. И на выходе мы видим
Код:

nmar.cmd -do reg1 223

NiOl 11-12-2009 15:25 1292587

А мне нравится 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 1294085

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 1294213

Цитата:

Цитата volk1234
Строка
For /F "Tokens=1* Delims==" %%i In ('Set $_') Do Call :%%j
Непонятна. »

тут как раз все просто - команда "Set $_" выдает список переменных, имя которых начинается на $_, из этого списка выделяются только значения (только то, что находится после знака "="), далее выполняется CALL по каждому такому значению

Цитата:

Цитата volk1234
означает что разделители - пробелы и знак равно могут быть? »

нет, только "="

Цитата:

Цитата volk1234
Что за хитрые переменные $_* »

$_1 - содержит имя 1-го параметра (начинается на "do") с подпараметрами (остальные);
$_2 - содержит имя 2-го параметра (начинается на "do") с подпараметрами (остальные);
...

каждая новая переменная $_* создается если параметр начинается на "do", иначе параметр "прибавляется" к последней такой переменной, команда:
Код:

Call Set $_%$I%=%%$_%$I%%%%$P%

volk1234 15-12-2009 01:35 1295481

Я прошу прощения за паузу - ну просто невозможно попасть за компьютер, настолько много дел перед н.г.

Вопрос следующий - а вот ключи которые у меня просто -

-ms
-unlockall
-full
-nomore
-kb

Для них отдельные строки писать, или оставить прямую обработку через IF "%1"="-ms" Goto
а потом ваш код + обработку -lreg1 ключей и -unreg1 -unreg2 ключей ?

amel27 15-12-2009 03:26 1295519

Цитата:

Цитата volk1234
Для них отдельные строки писать, или оставить прямую обработку »

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

volk1234 17-12-2009 01:22 1297255

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

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

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

Iska 17-12-2009 04:10 1297295

Можно так (удалит все вхождения «-»):
Код:

set key=-ms
set skey=%key:-=%
echo [%key%], [%skey%]


volk1234 17-12-2009 10:20 1297427

Это не универсально, тогда меня и моя процедура перехода устроит -

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

amel27 17-12-2009 10:40 1297448

Цитата:

Цитата volk1234
Все бы хорошо, да я запутался с отсечением знака '-' от имени ключа. Белиберда какая то получается. Как правильно отсечь минус от имени ключа? »

не совсем понял о чем речь, поэтому старый пример для ключей "-":
Код:

@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

volk1234 17-12-2009 23:03 1298099

Приведенный код
Код:

Call Set $_%$I%=%%$_%$I%%%%$P:~1%
отрезает не только '-' но и первые цифры, буквы от параметров.
Т.е. приведенная вами тестовая строчка дает результат

Код:

reg1 55
reg2 28 56

Второй вопрос - можно вставить такую обработку команды -unlockall, чтобы она выполнялась одна и другие ключи игнорировались?

Код:

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

  If "$_%$I%"=="unloackall" Goto :unlockall
GoTo :EOF

Ах да, еще мне не совсем понятно - как организовать в таком случае проверку синтаксиса - в случае указания несуществующего ключа, как завернуть скрипт на секцию :syntax_error

amel27 18-12-2009 01:16 1298155

Цитата:

Цитата volk1234
отрезает не только '-' но и первые цифры »

да, поторопился - исправил

Цитата:

Цитата volk1234
чтобы она выполнялась одна и другие ключи игнорировались? »

те, что после нее?

Цитата:

Цитата volk1234
как организовать в таком случае проверку синтаксиса - в случае указания несуществующего ключа, как завернуть скрипт на секцию :syntax_error »

например, так:
Код:

@Echo Off

Set $I=0& For %%i In (%*) Do Set $P=%%i& Call :CMD_PARSE
For /F "Tokens=1* Delims==" %%i In ('Set $_') Do 2>Nul Call :%%j||Call :SYNTAX_ERROR %%j

Exit /B

:REG1
  Echo REG1 %*
GoTo :EOF

:REG2
  Echo REG2 %*
GoTo :EOF

:SYNTAX_ERROR
  Echo ОШИБКА! Ключ "%1" не поддерживается!
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


volk1234 18-12-2009 02:01 1298180

Цитата:

Цитата volk1234
Второй вопрос - можно вставить такую обработку команды -unlockall, чтобы она выполнялась одна и другие ключи игнорировались? »

Цитата:

Цитата amel27
те, что после нее? »

Нет, просто чтобы игнорировались все команды кроме нее. Просто этот ключ отменяет действия всех других - поэтому нет смысла его выполнять наряду с ними.

amel27 18-12-2009 02:45 1298197

Код:

@Echo Off

Set $I=0& For %%i In (%*) Do Set $P=%%i& Call :CMD_PARSE
If Not Defined $SKIP For /F "Tokens=1* Delims==" %%i In ('Set $_') Do 2>Nul Call :%%j||Call :ERR0 %%j

Exit /B

:REG1
  Echo REG1 %*
Exit /B 0

:REG2
  Echo REG2 %*
Exit /B 0

:ERR0
  Echo ОШИБКА! Ключ "%1" не поддерживается!
GoTo :EOF

:CMD_PARSE
  If /I "%$P%"=="-unlockall" Set $SKIP=TRUE
  If /I "%$P:~0,1%"=="-" Set $P=%$P:~1%& Set /A $I=%$I%+1
  Call Set $_%$I%=%%$_%$I%%%%$P%
GoTo :EOF


volk1234 18-12-2009 10:29 1298343

Единственное - команда -unlockall просто вызывает завершение скроипта, а надо - переход в секцию :unlockall

amel27 18-12-2009 10:54 1298354

Цитата:

Цитата volk1234
команда -unlockall просто вызывает завершение скроипта »

не ЗАВЕРШЕНИЕ, а пропуск обработки парметров и ПРОДОЛЖЕНИЕ работы скрипта, можно и так:
Код:

@Echo Off

Set $I=0& For %%i In (%*) Do Set $P=%%i& Call :CMD_PARSE
If Defined $SKIP (GoTo :UnlockAll
) Else For /F "Tokens=1* Delims==" %%i In ('Set $_') Do 2>Nul Call :%%j||Call :ERR0 %%j

  Echo Код ПОСЛЕ обработки всех ключей
Exit /B

:UnlockAll
  Echo Код ВМЕСТО обработки ключей с последующим выходом
Exit /B

:REG1
  Echo REG1 %*
Exit /B 0

:REG2
  Echo REG2 %*
Exit /B 0

:ERR0
  Echo ОШИБКА! Ключ "%1" не поддерживается!
GoTo /B 0

:CMD_PARSE
  If /I "%$P%"=="-unlockall" Set $SKIP=TRUE
  If /I "%$P:~0,1%"=="-" Set $P=%$P:~1%& Set /A $I=%$I%+1
  Call Set $_%$I%=%%$_%$I%%%%$P%
GoTo :EOF

P.S. Если заменить "GoTo" на "CALL :", то в :UnlockAll будет "Код ВМЕСТО обработки ключей с последующим ПРОДОЛЖЕНИЕМ"

volk1234 18-12-2009 16:49 1298668

Что то в реальном скрипте не получается обработать несколько парамеров, (один параметр нормально)
похоже глотает пробелы скрипт между ключами и параметрами ключей...

Код:

:CORE
Set $I=0& For %%i In (%*) Do Set $P=%%i& Call :KEYS_PARSE
If Defined $SKIP (GoTo :UnlockAll
) Else For /F "Tokens=1* Delims==" %%i In ('Set $_') Do 2>Nul Call :%%j||Call :Syntax_Error %%j

Echo.
Echo Skript end working& Pause
Echo.

Exit /B 0

:KEYS_PARSE
  If /I "%$P%"=="-unlockall" Set $SKIP=TRUE
  If /I "%$P:~0,1%"=="-" Set $P=%$P:~1%& Set /A $I=%$I%+1
  Call Set $_%$I%=%%$_%$I%%%%$P%

GoTo :EOF


amel27 19-12-2009 06:17 1299040

Цитата:

Цитата volk1234
в реальном скрипте не получается обработать несколько парамеров »

для "реального скрипта" не хватает обработчиков ошибок, параметров и "unlockall", поэтому не ясно о чем речь, кроме того в строке
Код:

  Call Set $_%$I%=%%$_%$I%%%%$P%
GoTo :EOF

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

volk1234 20-12-2009 21:46 1300227

проблема была в другом- в конкретных секциях ожидались переменные %2 %3 которых теперь просто нет...
т.е. они могут быть, но их нет.


Время: 22:04.

Время: 22:04.
© OSzone.net 2001-