Не объявляется переменная

Тема в разделе "Пакетные файлы CMD, BAT", создана пользователем Foxik, 14 мар 2014.

  1. Foxik
    Оффлайн

    Foxik Новый пользователь

    Сообщения:
    24
    Симпатии:
    10
    где ошибка в сценарии? Почему не объявляются переменные cnt и summ?
    Код (DOS):

    @echo off
    rem SetLocal EnableExtensions EnableDelayedExpansion
    Echo List Local users:

    for /f "usebackq tokens=2 delims==" %%a in (`WMIC UserAccount Where "LocalAccount=True" Get Name /Format:List`) do (

    set /a cnt+=1
    set "User_%cnt%=%%a"
    set "summ=%summ%%cnt%"
    ECHO %cnt%. %%a
    )
    echo %summ%
     
    Последнее редактирование модератором: 14 мар 2014
  2. Dragokas
    Оффлайн

    Dragokas Very kind Developer Команда форума Супер-Модератор Разработчик Клуб переводчиков

    Сообщения:
    4.492
    Симпатии:
    4.307
    Способ 1.
    1) *Вам нужно заменить %cnt% на !cnt!
    2) снять с комментария 2-ю строку с директивами, т.к. EnableDelayedExpansion включает режим отложенного раскрытия переменных (разрешение на использование тех самых знаков !!)
    3) Что Вы хотите получить в переменной summ ?

    * Все команды, выполняемые внутри блока (цикл, скобки или однострочные команды) изменяют переменные среды только после выхода из данного блока.
    Чтобы получить актуальное значение переменной внутри этого же блока, нужно использовать механизм, указанный мною в пп.1,2.
    При этом не важно, где было произведено изменение значения переменной (внутри блока, через переход в подпрограмму или внешним окружением (например, псевдослучайное число, текущая дата/время). Все они при входе в блок команд запоминаются и "замораживаются".

    Использование режима DelayedExpansion имеет одну неприятную особенность: нельзя работать со знаками ! как со строкой (при этом знаки ! в выводе других команд также "глотаются").
    Поэтому иногда имеет смысл отключать или вовсе не использовать этот режим.

    Способ 2.
    Раскрывать значение переменной в другом процессе CMD:
    1) заменить тело цикла на код с использованием команды SET (при этом знаки % следует удвоить):

    Код (DOS):
    set /a cnt+=1
    call set "User_%%cnt%%=%%a"
    call set "summ=%%summ%%%%cnt%%"&rem здесь что писать не знаю; жду пояснения.
    call ECHO %%cnt%%. %%a
     
    Последнее редактирование: 14 мар 2014
    Kиpилл нравится это.
  3. Foxik
    Оффлайн

    Foxik Новый пользователь

    Сообщения:
    24
    Симпатии:
    10
    Спасибо, разобрался, все поправил, все работает...
    Вот итог:
    Код (DOS):

    @echo off
    Setlocal EnableDelayedExpansion
    Echo List Local users:
    for /f "usebackq tokens=2 delims==" %%a in (`WMIC UserAccount Where "LocalAccount=True" Get Name /Format:List`) do (
    set /a cnt+=1
    set "User_!cnt!=%%a"
    set "summ=!summ!!cnt!"
    ECHO !cnt!. %%a
    )
    Choice /C %summ% /M "choice users:"
     
    Переменная summ нужна была для параметра команды CHOICE... хотя теперь это и так понятно:rolleyes:
    Теперь еще кто-нибудь, также доходчево объяснил бы про EnableExtensions:whistle:
     
    Последнее редактирование модератором: 14 мар 2014
    Kиpилл нравится это.
  4. Dragokas
    Оффлайн

    Dragokas Very kind Developer Команда форума Супер-Модератор Разработчик Клуб переводчиков

    Сообщения:
    4.492
    Симпатии:
    4.307
    Оригинально придумано :)
    http://safezone.cc/threads/cmd-setlocal-i-rasshirennaja-obrabotka-komand.22629/
    --- Объединённое сообщение, 14 мар 2014 ---
    Другими словами, если я сделаю вот так:
    Код (Text):

    reg add "HKCU\Software\Microsoft\Command Processor" /v EnableExtensions /t REG_DWORD /d 0 /f
     
    Ваш последний скрипт перестанет работать ;)
     
    Последнее редактирование: 14 мар 2014
  5. Foxik
    Оффлайн

    Foxik Новый пользователь

    Сообщения:
    24
    Симпатии:
    10
    Не беда. => cmd.exe /X Enable
     
  6. Dragokas
    Оффлайн

    Dragokas Very kind Developer Команда форума Супер-Модератор Разработчик Клуб переводчиков

    Сообщения:
    4.492
    Симпатии:
    4.307
    Точнее /X:ON или /E:ON
    или посмотреть внимательно на Ваш первый скрипт.
     
  7. Foxik
    Оффлайн

    Foxik Новый пользователь

    Сообщения:
    24
    Симпатии:
    10
    Вот еще вариант без Setlocal:
    Код (DOS):
    @echo off
    Echo List Local users:
    for /f "usebackq tokens=2 delims==" %%a in (`WMIC UserAccount Where "LocalAccount=True" Get Name /Format:List`) do CALL:CREATE_CMD %%a
    Choice /C %summ% /M "choice users:"
    call set choi_usr=%%user_%errorlevel%%%

    echo %choi_usr%
    pause

    goto:eof
    :CREATE_CMD
    set /a cnt+=1
    set User_%cnt%=%1
    set summ=%summ%%cnt%
    ECHO %cnt%. %1
     
    Последнее редактирование модератором: 15 мар 2014
    Kиpилл нравится это.
  8. Dragokas
    Оффлайн

    Dragokas Very kind Developer Команда форума Супер-Модератор Разработчик Клуб переводчиков

    Сообщения:
    4.492
    Симпатии:
    4.307
    Foxik, да можно и так. Но для небольших конструкций слишком "расточительно" по объему кода.
    Кроме того, если Вас заинтересует скорость работы этих 3-х вариантов, то они соотносятся примерно так:

    1) точка отсчета затраченного времени - раскрытие значения через %%
    2) через !! ~ 2,5 раза медленнее
    3) через подпрограмму ~ 42 раза медленнее
    4) через call set ~ 60 раз медленнее

    Для конкретного кода, конечно, не имеет значения, а вот для пакетной обработки OVER 100 строк уже чувствуется (особенно на слабых машинах).

    P.S. Саму команду SetLocal указываю всегда, ибо после выхода из батника все измененные переменные окружения автоматически обнуляются
    (либо это можно сделать еще раньше - командой EndLocal)
    т.е. Вы можете указывать SetLocal EnableExtensions всегда и тогда Ваш скрипт не будет зависеть от указанного мною в реестре твика.
     
    Последнее редактирование: 15 мар 2014
    Kиpилл нравится это.

Поделиться этой страницей