[CMD] Операторы выбора в командной строке Windows

alex-s

Новый пользователь
Сообщения
21
Реакции
1
В Bash есть несколько команд, который могут позволить составить сценарий, в котором можно описать несколько действий и предоставить пользователю ввести номер нужной позици и тогда выполняются определенные команды, если пользователь ничего не выбрал, то подставляется номер по умолчанию и выполняются команды соответствующие данному номеру.

Как это можно осуществить в командной строке Windows ???

Приведите пожалуйста примеры или статьи с подробным разбором особенности таких команд в BATCH ( без использования каких-либо других языков или установки утилит)

Спасибо.
 
В Bash есть несколько команд, который могут позволить составить сценарий, в котором можно описать несколько действий и предоставить пользователю ввести номер нужной позици и тогда выполняются определенные команды, если пользователь ничего не выбрал, то подставляется номер по умолчанию и выполняются команды соответствующие данному номеру.
Вот вы и приведите пример, а то как то догадываться неправильно.
 
Вот вы и приведите пример, а то как то догадываться неправильно.

CMD/BATCH:
#!/bin/bash

echo -n "Продолжить? (y/n) "

read item
case "$item" in
    y|Y) echo "Ввели «y», продолжаем..."
        ;;
    n|N) echo "Ввели «n», завершаем..."
        exit 0
        ;;
    *) echo "Ничего не ввели. Выполняем действие по умолчанию..."
        ;;
esac

Код:
while getopts ":abcde:fg" Option
# Начальное объявление цикла анализа опций.
# a, b, c, d, e, f, g -- это возможные опции (ключи).
# Символ : после опции 'e' указывает на то, что с данной опцией может идти
# дополнительный аргумент.
do
  case $Option in
    a ) # Действия, предусмотренные опцией 'a'.
    b ) # Действия, предусмотренные опцией 'b'.
    ...
    e)  # Действия, предусмотренные опцией 'e', а так же необходимо обработать $OPTARG,
        # в которой находится дополнительный аргумент этой опции.
    ...
    g ) # Действия, предусмотренные опцией 'g'.
  esac
done
shift $(($OPTIND - 1))
# Перейти к следующей опции.

Код:
#!/usr/bin/env bash
# getopts.sh

# Обработка опций командной строки с помощью 'getopts'.

# Попробуйте вызвать этот сценарий как:
# 'scriptname -mn'
# 'scriptname -oq qOption' (qOption может быть любой произвольной строкой.)
# 'scriptname -qXXX -r'
#
# 'scriptname -qr'    - Неожиданный результат: "r" будет воспринят как дополнительный аргумент опции "q"
# 'scriptname -q -r'  - То же самое, что и выше
#  Если опция ожидает дополнительный аргумент ("flag:"), то следующий параметр
#  в командной строке, будет воспринят как дополнительный аргумент этой опции.

NO_ARGS=0
E_OPTERROR=65
ME=$(basename $0)

if [[ $# -eq ${NO_ARGS} ]]  # Сценарий вызван без аргументов?
then
  echo
  echo "Порядок использования: ----$ME---- options (-mnopqrs)"
  echo
  exit $E_OPTERROR        # Если аргументы отсутствуют -- выход с сообщением
                          # о порядке использования скрипта
                       
fi
# Порядок использования: scriptname -options
# Обратите внимание: дефис (-) обязателен


while getopts ":mnopq:rs" Option
do
echo
echo -e "\$OPTIND:" --- $OPTIND
echo
  case $Option in
    m     ) echo "Сценарий #1: ключ -m-";;
    n | o ) echo "Сценарий #2: ключ -$Option-";;
    p     ) echo "Сценарий #3: ключ -p-";;
    q     ) echo "Сценарий #4: ключ -q-, с аргументом \"$OPTARG\"";;
    # Обратите внимание: с ключом 'q' должен передаваться дополнительный аргумент,
    # в противном случае отработает выбор "по-умолчанию".
    r | s ) echo "Сценарий #5: ключ -$Option-"'';;
    *     ) echo "Выбран недопустимый ключ.";;   # ПО-УМОЛЧАНИЮ
     esac
done
shift $(($OPTIND - 1))
# Переход к очередному параметру командной строки.
echo
exit 0

# NO_ARGS=0 - переменная для сравнения с числом аргументов,
# передаваемых при запуске скрипта
# $# - количество аргументов, переданных при вызове скрипта

# if [[ $# -eq ${NO_ARGS} ]] - если число аргументов равно 0 , тогда выполняются
# команды после then

# basename $0 - эта команда отсекает лишние префиксы и путь к скрипту
# и остается только имя скрипта

# E_OPTERROR=65 - переназначение exit-статуса, результата работы скрипта
# while getopts ":mnopq:rs" Option - происходит разбор аргументов,
# после ключа q: идет двоеточие , а значит этот ключ должен иметь дополнительный
# аргумент(-ы) – не имеются ввиду ключи -  rs
# Результат разбора аргументов (ключей), передается в переменную  Option
# затем используя значение (-я) переменной Option
# оператор case выбирает нужный вариант, в соответствии со
# значением, взятым из переменной $Option

# $OPTIND - содержит номер итерации (номер прохода цикла)
# С командой getopts очень тесно взаимосвязаны скрытые
# переменные. $OPTIND -- указатель на аргумент (OPTion INDex)
# Обычно getopts упаковывается в цикл while,
# в каждом проходе цикла извлекается очередная
# опция и ее аргумент (если он имеется),
# Обрабатывается, затем уменьшается на 1 скрытая
# переменная $OPTIND и выполняется переход к началу новой итерации.

Код:
#!/bin/bash
set -e

ME=`basename $0`
function print_help() {
    echo "Работа с файлом test_file"
    echo
    echo "Использование: $ME options..."
    echo "Параметры:"
    echo "  -c          Создание файла test_file."
    echo "  -w text     Запись в файл строки text."
    echo "  -r          Удаление файла test_file."
    echo "  -h          Справка."
    echo
}

function create_file() {
    touch test_file
}

function write_to_file {
    echo "$TEXT" >> test_file
}

function remove_file {
    rm test_file
}

# Если скрипт запущен без аргументов, открываем справку.
if [ $# = 0 ]; then
    print_help
fi

while getopts ":cw:r" opt ;
do
    case $opt in
        c) create_file;
            ;;
        w) TEXT=$OPTARG;
            write_to_file
            ;;
        r) remove_file
            ;;
        *) echo "Неправильный параметр";
            echo "Для вызова справки запустите $ME -h";
            exit 1
            ;;
        esac
done




Итак, что мы имеем?
•    Команда set -e остановит скрипт, если при его выполнении возникнет ошибка (подробнее о других опциях здесь).
•    Основные операции скрипта упакованы в функции. Конечно, глупо помещать в функции по одной команде, но это лишь для примера, в реальности их может быть ну очень много.
•    Функция getopts разбирает переданные аргументы. За ней перечисляются допустимые опции. Двоеточие после опции 'w' означает, что c данной опцией идет дополнительный аргумент, который помещается в переменную $OPTARG.
•    Опции можно комбинировать, но стоит учитывать то, что они выполняются по порядку. Это значит, что если мы выполним script -rc то сначала файл будет удален, а затем создан. При этом, если файла не существовало, то скрипт завершится с ошибкой, не дойдя до создания файла.
•    Также стоит учитывать то, что после ключа 'w' обязательно должен следовать аргумент. Если он будет отсутствовать, то скрипт выполнит опцию '*' (по умолчанию). Интересно, что если запустить script -wr Hallo, то опция 'r' будет воспринята как дополнительный параметр к опции 'w', а 'Hallo' проигнорировано. Правильно будет script -w Hallo -r

Код:
#!/usr/bin/env bash

set -e

ME =$(basename $0)
f=test_file

function print_help()
{
    echo
    echo "*************Работа с файлом $f******************"
    echo
    echo "Использование: ---$ME--- параметры..."
    echo
    echo "-------------------Параметры:--------------------------"
    echo "  -c          Создание файла $f."
    echo "  -w text     Запись в файл строки --- какое_нибудь_слово --- ."
    echo "  -r          Удаление файла $f."
    echo "  -h          Справка."
    echo
}

function create_file()
{
    touch $f
}

function write_to_file
{
    echo "$TEXT" >> $f
}

function remove_file
{
    rm $f
}

# Если скрипт запущен без аргументов, открываем справку.
if [ $# = 0 ]; then
    print_help
fi

while getopts ":cw:rh" opt ;
do
    case $opt in
        c) create_file
           ls | grep $f
            ;;
        w) TEXT=$OPTARG
            write_to_file
            nano $f
            ;;
        r) remove_file
           ls | grep $f
            ;;
        h) print_help
            ;;
        *) echo
           echo "Неправильный параметр";
           echo
           echo "Для вызова справки запустите --- ./$ME -h";
           echo
            exit 1
            ;;
        esac
done

# set -e - прекращение работы скрипта, если exit-status не равен 0.
# if [ $# = 0 ] - если аргументов нет, вызывается функция  print_help
# while getopts ":cw:r" opt - разбор опций и передача их по очереди
# (в каждой итерации) в переменную opt

# c) - вызов функции create_file, создаем файл
# ls | grep $f - проверяем создание файла - $f (test_file)

# w) - вызов функции write_to_file
# nano $f - проверка, записана ли строка в файл

# r) - вызов функции remove_file
#  ls | grep $f - проверка удаления файла

Вызов без параметров
   ./selection-option.sh
Создание файла
./selection-option.sh -c

Код:
#!/bin/bash

PS3='Выберите ваш любимый овощ: ' # строка приглашения к вводу (prompt)

echo

select vegetable in "бобы" "морковь" "картофель" "лук" "брюква"
do
  echo
  echo "Вы предпочитаете $vegetable."
  echo ";-))"
  echo
  break  # если 'break' убрать, то получится бесконечный цикл.
done
exit 0

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

Код:
#!/usr/bin/env /bash

PS3='Выберите ваш любимый овощ: '
echo
choice_of()
{
    select vegetable
# список выбора [in list] отсутствует, поэтому 'select' использует входные аргументы функции.
do
        echo
        echo "Вы предпочитаете $vegetable."
  echo ";-))"
  echo
  break
done
}
choice_of бобы рис морковь редис томат шпинат
#         $1   $2  $3      $4    $5    $6
#         передача списка выбора в функцию choice_of()
exit 0

Код:
# Изменение строки приветствия
PS3='Выберите операционную систему: '

select OS in "Linux" "Windows" "Mac OS" "BolgenOS"
do
  echo
  echo "Вы выбрали $OS!"
  echo
  break
done

Код:
#!/bin/bash

PS3="Выберите исполняемый файл: "

select file in ~/scripts/tmp/s* quit
do
if [[ -f $file]]
then
${file}
else
break
fi
done

exit 0

# quit – это команда, которая производит выход из сценария,
# в данном случае она стоит в одном из пунктов меню
 
Намёка на статью у меня нет, но достаточный минимум описан в справке choice /?
Доступна на ОС Vista и выше.
CHOICE [/C список] [/N] [/CS] [/T тайм-аут /D элемент] [/M текст]

Описание.
Эта программа позволяет выбирать элемент из списка элементов
и возвращает индекс выбранного элемента.

Параметры:
/C список Создаваемый список выбираемых элементов.
Список по умолчанию "YN".

/N Скрытие списка элементов в приглашении.
Перед приглашением выводится сообщение
и элементы остаются доступными для выбора.

/CS Включение учета регистра при выборе элементов.
По умолчание в программе регистр символов не учитывается.

/T тайм-аут Число секунд перед выбором элемента по умолчанию.
Допустимыми являются значения от 0 до 9999.
Если указан 0, отсутствует пауза перед выбором
элемента по умолчанию.

/D элемент Элемент, выбираемый по умолчанию через nnnn секунд.
Символ должен присутствовать в наборе элементов
в параметре /C; значение nnnn задается в параметре /T.

/M текст Сообщение, отображаемое перед
приглашением. Если не указано, программа
выводит только приглашение.

/? Вывод справки по использованию.

Примечание
Переменная среды ERRORLEVEL получает значение индекса
клавиши, соответствующей выбранному элементу. Первый элемент
в списке возвращает значение 1, второй - 2 и т.д.
Если пользователь нажимает клавишу, не соответствующую допустимому
выбору, подается звуковой сигнал. Если обнаруживается ошибка,
возвращается значение ERRORLEVEL 255. Если нажимаются клавиши
CTRL+BREAK или CTRL+C, программа возвращает значение ERRORLEVEL 0.
При использовании параметров ERRORLEVEL в пакетной программе их
следует перечислять по убыванию.

Примеры:
CHOICE /?
CHOICE /C YNC /M "Y - Да, N - Нет, C - Отмена."
CHOICE /T 10 /C ync /CS /D y
CHOICE /C ab /M "a" для выбора параметра 1 и "b" для выбора параметра 2.
CHOICE /C ab /N /M "a" для выбора параметра 1 и "b" для выбора параметра 2.
Пример:
Код:
choice /C YN /D Y /T 5 /M "Y - Да, N - нет"

if %errorlevel%==1 echo Вы выбрали "Да"
if %errorlevel%==2 echo Вы выбрали "Нет"
По истечению 5 секунд будет автоматически выбран вариант Y.
Порядковый номер выбранной буквы будет сохранён в виде кода возврата ошибки (errorlevel).

Учтите, что регистр символов (если не указан ключ /CS) игнорируется только в английском алфавите.
 
Последнее редактирование:
Вот ещё конструкция by Dragokas
Код:
>nul chcp 866
:menu
cls
echo. -    [1] One
echo. -    [2] Two
echo. -    [0] Выход
echo. Введите цифру пункта меню и нажмите ENTER.

set x=
set /p x=
if "%x%"=="1" goto one
if "%x%"=="2" goto two
if "%x%"=="0" goto GOOUT
goto menu
 

Что это за конструкция ?
chcp 866 - это смена кодовой страницы.
а в связке с >nul - это подавление вывода информации "... о смене кодовой страницы" ?

:menu

И почему часто вижу написание метки перед какой-то частью сценария, это что правило "хорошего тона" при написании скрипта, даже если метка не используется ???
 
Последнее редактирование:
:menu

И почему часто вижу написание метки перед какой-то частью сценария, это что правило "хорошего тона" при написании скрипта, даже если метка не используется ???
А как же это ? goto menu
Этот пример используется в программе по нажатию на паучка у меня в подписи.
 
Последнее редактирование:
понял ... возврат в начало пока не будет выбран нужный вариант, а как добавить команду по-умолчанию, например по истечении какого-то времени программа закрывается с сообщением, или подставляет сама значение по умолчанию ???
 
Код:
set x=2
set /p x=
if "%x%"=="1" goto one
if "%x%"=="2" goto two
if "%x%"=="0" goto GOOUT
goto menu
set x=2 - второе действие будет выбрано. Осталось таймер прикрутить.. Есть вариант с пингом.
Код:
>nul ping 127.0.0.1 -n 6
Но при каком условии ?.. Лучше с choice, а то так сразу запустится..
 
Последнее редактирование:
возврат в начало пока не будет выбран нужный вариант, а как добавить команду по-умолчанию, например по истечении какого-то времени программа закрывается с сообщением, или подставляет сама значение по умолчанию ???
Только через команду choice. См. пост # 2.
 
Ой, это нужно спрашивать у greg zaharov. Он обитает на сером форуме и на киберфоруме.
Он как-то писал подобную обёртку через нестандартный кодинг, добавив для команды set /p таймаут. Я наверное уже не найду поиском этот код. Давно было.
или вам без таймаута?
 
таймаут обязательно буду использовать, вот что я написал, но отсюда пришлось убрать 0, тогда скрипт почему то не работает...

CMD/BATCH:
@echo off
cls
echo.
echo               IPconfig - выбор опций
echo *********************************************************
echo. 1  -  /all           -  Вывод подробных сведений о конфигурации.
echo.
echo. 2  -  /release       -  Освобождение адреса IPv4 для указанного адаптера.
echo.
echo. 3  -  /release6      -  Освобождение адреса IPv6 для указанного адаптера.
echo.
echo. 4  -  /renew         -  Обновление адреса IPv4 для указанного адаптера.
echo.
echo. 5  -  /renew6        -  Обновление адреса IPv6 для указанного адаптера.
echo.
echo. 6  -  /flushdns      -  Очистка кэша сопоставителя DNS.
echo.
echo. 7  -  /registerdns   -  Обновление всех DHCP-аренд и перерегистрация DNS-имен
echo.
echo. 8  -  /displaydns    -  Отображение содержимого кэша сопоставителя DNS.
echo.
echo. 9  -  /showclassid   -           Отображение всех допустимых для этого адаптера
echo                                  идентификаторов классов DHCP.
echo.
echo  0  -  /allcompartments /all  -   Отображение подробных сведений обо
echo                                  всех секциях
echo.
echo. *********************************************************
echo.
choice /C 123456789 /M "Какую из опций -- IPconfig -- вы желаете использовать"
echo.

If Errorlevel 9 Goto 9
If Errorlevel 8 Goto 8
If Errorlevel 7 Goto 7
If Errorlevel 6 Goto 6
If Errorlevel 5 Goto 5
If Errorlevel 4 Goto 4
If Errorlevel 3 Goto 3
If Errorlevel 2 Goto 2
If Errorlevel 1 Goto 1
#If Errorlevel 0 Goto 0

Goto End

:9
cls
ipconfig /showclassid
Goto End

:8
cls
ipconfig /displaydns
Goto End

:7
cls
ipconfig /registerdns
Goto End

:6
cls
ipconfig /flushdns
Goto End


:5
cls
ipconfig /renew6
Goto End

:4
cls
ipconfig /renew
Goto End

:3
cls
ipconfig /release6
Goto End


:2
cls
ipconfig /release
Goto End

:1
cls
ipconfig /all
Goto End

#:0
cls
ipconfig /allcompartments /all
Goto End

: End
И если вывод большой , а как поставить ограничитель, чтобы вывод был по нажатию клавиши пользователем
Постраничный, а не все сразу
 
CMD/BATCH:
cls
:main_menu
@Color f0
title Menu
echo.
echo  Shipiloff Vitaliy  - androidp1.ru                                 v3.92.80
echo.
echo. 1 - Device attached?                           9 - Install Bootanimation.zip
echo.
echo. 2 - Move                                      10 - Memory and Partitions
echo.
echo. 3 - Install Android App to Device             11 - Run Script
echo.
echo. 4 - Reboot Devices                            12 - Backup
echo.
echo. 5 - Fastboot                                  13 - Odex system *.apk and *.jar
echo.
echo. 6 - Unlock Gesture Key / Pin Key              14 - Screenshot/Record
echo.
echo. 7 - Manual Command and Unlock Bootloader      15 - Root Android         
echo.
echo. 8 - Check for update program Adb Run          16 - Download Android Driver
echo.
set mymenu=x
set /p mymenu="Input: "
cls
if /i %mymenu%==1 goto attached_device
if /i %mymenu%==2 goto move_files
if /i %mymenu%==3 goto apps_install
if /i %mymenu%==4 goto reboot_device
if /i %mymenu%==5 goto fastboot_menu_general
if /i %mymenu%==6 goto unlock_gesturekey
if /i %mymenu%==7 goto manual_unlock_bootloader
if /i %mymenu%==8 goto update_adb_run
if /i %mymenu%==9 goto instbootzip
if /i %mymenu%==10 goto memapart
if /i %mymenu%==11 goto runfor
if /i %mymenu%==12 goto adbbackup
if /i %mymenu%==13 goto odexm
if /i %mymenu%==14 goto screenshot_menu
if /i %mymenu%==15 explorer.exe "http://androidp1.ru/root-2/"
if /i %mymenu%==16 explorer.exe "http://androidp1.ru/drviver-for-android/"
goto main_menu
Вот пример. Adb Run. Обзор функций и возможности программы - Android +1
 
Последнее редактирование:
И если вывод большой , а как поставить ограничитель, чтобы вывод был по нажатию клавиши пользователем
Постраничный, а не все сразу
Никак. Лучше в текст выводить, если надо анализировать. Типа так -
CMD/BATCH:
ipconfig /allcompartments /all>%tmp%\all.txt && %tmp%\all.txt
 
но отсюда пришлось убрать 0, тогда скрипт почему то не работает...
Потому что у нуля errorlevel будет = 1, а у 9 = 10. (если 0 на первом месте).

Для 2-разрядных чисел вот такой способ придумал:
CMD/BATCH:
@echo off
set TimeOut=2

echo Варианты:
echo 00
echo 01
echo ...
echo 99
echo.
set /p "x=Какую из опций вы желаете использовать? " <NUL
choice /C 0123456789 /D 0 /T %TimeOut% >NUL
set c=%errorlevel%
set /a c-=1
set /p "x=%c%" <NUL
choice /C 0123456789 /N /D 0 /T %TimeOut%
set d=%errorlevel%
set /a d-=1
echo Ваш выбор: %c%%d%

call :%c%%d%
pause
goto :eof

:00
echo Sub 00
exit /b

:01
echo Sub 01
exit /b
:: и т.д.

На ввод каждого разряда даётся таймаут в 2 сек.

Phoenix, привет :)
И если вывод большой , а как поставить ограничитель, чтобы вывод был по нажатию клавиши пользователем
CMD/BATCH:
ipconfig /allcompartments /all | more
Пролистывание кнопкой Space.
 
Я вот так еще могу предложить:

CMD/BATCH:
@echo off
SetLocal EnableExtensions EnableDelayedExpansion
set t=0
set /a r=%t%+1


Echo Выберите один из вариантов, иначе будет выбран вариант 3
Call :serial


call :choice "Вариант 1" "Вариант 2" "Вариант 3" "Главное меню"

if %ErrorLevel% EQU 1 (echo выбран вариант 1
                                            pause)
if %ErrorLevel% EQU 2 (echo выбран вариант 2
                                            pause)
if %ErrorLevel% EQU 3 (echo выбран вариант 3
                                            pause)
if %ErrorLevel% EQU 4 (echo выбран вариант 4
                                            pause)

exit /b

:serial
if %r% LEQ 5 (
set /a r=%r%+1
echo %r%
call :timer
cls
goto serial) else (
Call :choice)
exit /b

:timer
set /a paused=%time:~7,-3%+2
if %paused% GEQ 10 set /a paused=!paused!-10
:check
set /a faq=%time:~7,-3%
if not %paused%==%faq% goto :check


:choice

setlocal
if "%~1"=="" (
  set result=0
  goto choice_3
)
set count=0
:choice_1
set /a count+=1
echo %count%. %~1
shift
if not "%~1"=="" goto choice_1
:choice_2
set /p result=Ваш выбор (1-%count%):
for /l %%i in (1, 1, %count%) do if "%result%"=="%%i" goto choice_3
goto choice_2
:choice_3
endlocal & exit /b %result%ce_3
)
set count=0
:choice_1
set /a count+=1
echo %count%. %~1
shift
if not "%~1"=="" goto choice_1
:choice_2
set /p result=Ваш выбор(1-%count%):
for /l %%i in (1, 1, %count%) do if "%result%"=="%%i" goto choice_3
goto choice_2
:choice_3
endlocal & exit /b %result%

Только таймер переприкрутить надо куда то в другое место кажется.
 
Последнее редактирование:
Кирилл, разумеется :) Отдельным процессом только, так то у тебя таймер блокирует ввод.
 
Назад
Сверху Снизу