Я разделить проблему на три части. Ввод данных в массив, получение данных из массива и имитация команды case
, отсутствующей в партии.
@echo off
setlocal enableextensions enabledelayedexpansion
set /p "data=Input data:"
Давайте предположим, что пользователь вводит только числовые значения (чтобы избежать все необходимые проверки и только смотреть на проблему), как указано, разделенных пробелами. Поместите их в «массив». Нет, массивы не присутствуют в пакетных сценариях, но могут быть смоделированы, давая переменным собственные имена.
set "arrayLength=0"
for %%e in (%data%) do (
set /a "arrayLength+=1"
set "a[!arrayLength!]=%%e"
)
Это перебирает входные данные, и для каждого элемента, счетчик увеличивается на единицу, и переменный с именем a[
+ counter value
+ ]
создаются. Нет, это не массив, а просто переменная с именем, позволяющая нам имитировать массив sintax. По мере того как счетчик (arrayLength
) является неоспоримым изменен внутри цикла, задержка расширения требуется, чтобы прочитать эту измененную величину, и синтаксис для изменения переменного считываются из %var%
к !var!
Теперь данные находятся в «массиве». Мы собираемся перебирать «массив», проверяя его содержимое.
for /l %%i in (1 1 %arrayLength%) do (
echo element %%i is : !a[%%i]!
)
Синтаксис для чтения содержимого каждого из элементов требует отсроченного расширения. В этом случае мы не изменяем значение внутри блока, но имя прочитанной переменной генерируется динамически на каждой итерации. Помните, никаких массивов, просто переменные с повторным именем. И мы сгенерируем имя, используя переменную for
.
Как проверить значения «массива»?
echo Test IF
for /l %%i in (1 1 %arrayLength%) do (
if "!a[%%i]!"=="1" (
echo Case 1
) else if "!a[%%i]!"=="2" (
echo Case 2
) else if "!a[%%i]!"=="3" (
echo Case 3
) else if "!a[%%i]!"=="4" (
echo Case 4
) else if "!a[%%i]!"=="5" (
echo Case 5
) else if "!a[%%i]!"=="6" (
echo Case 6
) else (
echo NO CASE
)
)
Это перебирает в «массиве» и использует каскадную IF
синтаксиса для проверки допустимых значений. Это легко кодировать, быстро, но не наиболее удобно поддерживать, если есть частые изменения в случаях.
Альтернативой каскаду IF является использование подпрограмм. В зависимости от значения элемента «массив» вызовите одну метку или другую. Просто назовите этикетки адекватно.
Затем вы можете проверить, существует ли метка/подпрограмма, а затем вызвать ее.
Или вы можете позвонить напрямую без предварительной проверки и проверки ошибок в вызове, которые указывают, что метка не существует.
Или можно определить таблицу подпрограмм.
Для образца, если следующие метки определены
:case[1]
echo Case 1
goto :eof
:case[2]
echo Case 2
goto :eof
:case[3]
echo Case 3
goto :eof
:case[4]
echo Case 4
goto :eof
:case[5]
echo Case 5
goto :eof
:case[6]
echo Case 6
goto :eof
Кодекса называть это подпрограммой с предыдущей проверкой существования в пакетном файле (%~f0
является текущим командным файлом с полным путем) может быть
rem Use labels in batch with previous test of existence
for /l %%i in (1 1 %arrayLength%) do (
findstr /l /c:":case[!a[%%i]!]" "%~f0" > nul 2>nul
if not errorlevel 1 (
call :case[!a[%%i]!]
) else (
echo NO CASE
)
)
findstr
Это использует для чтения текущих пакетного поиска файлов для :case[n]
этикетки. Без ошибок метка была найдена и вызов выполнен. Но чтение командного файла для проверки существования метки не является самой быстрой операцией.
Чтобы не проверять наличие этикетки и непосредственно сделать вызов, этот код может быть использован
rem Use labels in batch without check
for /l %%i in (1 1 %arrayLength%) do (
ver>nul
call :case[!a[%%i]!] 2>nul
if errorlevel 1 echo NO CASE
)
«вер> nul` линия symply обеспечивает Равно очищаются перед вызовом подпрограммы. Вызов выполняется, и проверяется уровень ошибок. Но нет способа узнать, исходит ли уровень ошибок из команды вызова или изнутри вызываемой подпрограммы.
Другим вариантом является наличие таблицы рутинов для вызова каждого из возможных значений элементов в массиве. Таким образом, если таблица для каждого из разрешенных элементов создается, указывая на этикетках подпрограммах
set "func[1]=:case[1]"
set "func[2]=:case[2]"
set "func[3]=:case[3]"
set "func[4]=:case[4]"
set "func[5]=:case[5]"
set "func[6]=:case[6]"
Следующий код может вызвать adecuated подпрограмму, cheching если функция стоимости определяется
for /l %%i in (1 1 %arrayLength%) do (
for %%v in (!a[%%i]!) do if defined func[%%v] (
call !func[%%v]!
) else (
echo NO CASE
)
)
Внутреннее значение необходимо для получения ссылки на значение внутри «массива», которое будет использоваться для доступа к имени функции внутри массива func
.
И ..... что-нибудь лучшее, что можно было бы себе представить.
В конце концов, какой код следует использовать? Что работает для вас. Все зависит от реальной проблемы.
Каскад IF является быстрым и легким, но для проблемы с частыми меняющимися случаями сложнее поддерживать.
Findstr занимает много времени.
Звонок без проверки может быть настоящим nigntmare.
Таблица функций находится посередине. Не так быстро, как наличие всего кода в блоке, как в решении IF, но быстрее, чем findstr
, проверяя определение подпрограммы. Это не сложно скомпоновать, но для небольших проблем нетрудно.
Для простых случаев нужны только конструкции IF
. Для сложных проблем, если код длинный, а случаи необходимо изменить, добавить, ... таблица функций упрощает работу.
Таким образом, это может привести к
@echo off
setlocal enableextensions enabledelayedexpansion
set /p "data=Input data:"
set "arrayLength=0"
for %%e in (%data%) do (
set /a "arrayLength+=1"
set "a[!arrayLength!]=%%e"
)
rem func[ allowedValue ] = label to call
set "func[1]=:handleCase_1"
set "func[2]=:handleCase_2"
set "func[3]=:handleCase_3"
set "func[4]=:handleCase_4"
set "func[5]=:handleCase_5"
set "func[6]=:handleCase_6"
for /l %%i in (1 1 %arrayLength%) do (
for %%v in (!a[%%i]!) do if defined func[%%v] (
call !func[%%v]!
) else (
echo NO CASE
)
)
for /l %%i in (1 1 %arrayLength%) do (
if "!a[%%i]!"=="1" (
echo Case 1
rem Or, we can
rem call :handleCase_1
) else if "!a[%%i]!"=="2" (
echo Case 2
) else if "!a[%%i]!"=="3" (
echo Case 3
) else if "!a[%%i]!"=="4" (
echo Case 4
) else if "!a[%%i]!"=="5" (
echo Case 5
) else if "!a[%%i]!"=="6" (
echo Case 6
) else (
echo NO CASE
)
)
endlocal
exit /b
:handleCase_1
echo Case 1
goto :eof
:handleCase_2
echo Case 2
goto :eof
:handleCase_3
echo Case 3
goto :eof
:handleCase_4
echo Case 4
goto :eof
:handleCase_5
echo Case 5
goto :eof
:handleCase_6
echo Case 6
goto :eof
Большое спасибо. Первые четыре части кода, которые вы дали, отлично работали. У меня есть еще одна работа, которая должна быть сделана там в четвертой части. После echo case1 необходимо сделать вызов (скажем, goto func1), значение func1 определено после 4-й части. этот goto func1 должен присутствовать в каждом случае. Тем не менее программа должна работать нормально. Это возможно? Заранее спасибо. Следовательно, func1 следует вызывать из if!! A [%% i]! "==" 1 "и если"! A [%% i]! "==" 3 "и если"! A [%% i] ! "==" 5 " , если в качестве входного сигнала указано значение 1 3 5. – KeeKu
@ user3173444: 'func1' будет использоваться из более чем одного места, затем закодировать его как подпрограмму и вызвать его с помощью' call: func1'. Пятый и шестой разделы кода в ответе показывают, как его определить. Тогда, в структуре if у вас будет 'if '! A [%% i]!" == "1" ( .... что здесь и называть: func1 ) else if "! A [%% i]! "==" 2 "( .... ) else if"! a [%% i]! "==" 3 "( .... что здесь и называть: func1 ) else ... ' –
Да, это сработало. Благодарю. – KeeKu