Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Пакетные файлы CMD, BAT > Трюки в CMD


Автор: Jin X 14.10.16, 08:16
Проверку поддержки расширенной обработки команд и включение этой расширенной обработки, а также отложенного расширения переменных среды я делаю следующим образом:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    if [%cmdextversion%] == [] goto nocmdext
    if not cmdextversion 1 goto nocmdext
    setlocal EnableExtensions EnableDelayedExpansion
    if errorlevel 1 goto nocmdext
Не уверен, что это наиболее оптимальный вариант (вероятно, он избыточен), предложите свой :)


Вывод сообщений с обрамлением чёрточками (символ # заменяется на !):
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    @echo off
    setlocal EnableExtensions EnableDelayedExpansion
     
    echo.
    call :ShowMsg "Hello, my friend#"
    exit /b
     
    :ShowMsg str(#=!)
    set _s=%~1&call :StrLen !_s!&call :StrRep !_l! -
    echo %_s:#=^^!%
    call :StrRep %_l% -
    exit /b
    :StrLen str
    set _=%*&set _l=0&(for /l %%i in (1,1,256) do if #!_! neq # set /a _l+=1&set _=!_:~0,-1!)&exit /b
    :StrRep count str
    set _=&(for /l %%i in (1,1,%1) do set _=!_!%2)&echo !_!&exit /b
p.s. Кол-во чёрточек ограничено 256 символами (для упрощения).
Есть и более сложные (быстрые и универсальные) процедуры вычисления длины строки.


Вывод сообщений без перевода строки и задержка (демонстрация вентилятора):
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    @echo off
    setlocal EnableExtensions EnableDelayedExpansion
     
    for /l %%i in (1,1,10) do (
      call :Write "|◘"
      call :Delay 10
      call :Write /◘
      call :Delay 10
      call :Write -◘
      call :Delay 10
      call :Write \◘
      call :Delay 10
    )
    exit /b
     
    :Write str
    set /p=%1<nul
    exit /b
     
    :Delay hundredth
    call :GetTicks _a
    :_WaitDelay
    call :GetTicks _b
    set /a _b=_b-_a
    if %_b% lss 0 set /a _b+=8640000
    if %_b% lss %~1 goto _WaitDelay
    exit /b
     
    :GetTicks var
    set _t=%time: =0%
    set /a %1=1%_t:~9,2%-100+(1%_t:~6,2%-100)*100+(1%_t:~3,2%-100)*6000+(1%_t:~0,2%-100)*360000
    exit /b
Не потеряйте здесь символы с кодом 8 !!! (◘)
p.s. Суть вывода сообщений без перевода строки сводится к одной простой команде:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    set /p=Строка<nul
или так:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    <nul set /p=Строка


Ещё один пример с задержкой (определение прошедшего времени):
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    @echo off
    setlocal EnableExtensions EnableDelayedExpansion
     
    echo.
    echo Подождите, команда выполняется...
    call :GetTicks tick1
     
    :: Выполняем команду
    dir c:\ /s > nul
     
    call :GetTicks tick2
    set /a hs=%tick2%-%tick1%
    if %hs% lss 0 set /a hs+=8640000
    set /a h=%hs%/360000
    set /a m=(%hs%/6000)%%60
    set /a s=(%hs%/100)%%60
    set /a hs=%hs%%%100
    echo Прошедшее время: %h% час %m% мин %s%.%hs% сек.
    pause
    exit /b
     
    :GetTicks var
    set _t=%time: =0%
    set /a %1=1%_t:~9,2%-100+(1%_t:~6,2%-100)*100+(1%_t:~3,2%-100)*6000+(1%_t:~0,2%-100)*360000
    exit /b


Чтение ini-файлов:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    @ECHO OFF
    :: Check Windows version
    IF NOT "%OS%"=="Windows_NT" GOTO Syntax
    :: Check command line
    ECHO.%1 | FIND "?" >NUL
    IF NOT ERRORLEVEL 1 GOTO Syntax
    IF [%3]==[] GOTO Syntax
    :: Check if INI file exists
    IF NOT EXIST "%~f1" GOTO Syntax
     
    :: Keep variables local and enable delayed variable expansion
    SETLOCAL ENABLEDELAYEDEXPANSION
     
    :: Read variables from command line
    SET INIFile="%~f1"
    SET INISection=%~2
    SET INIKey=%~3
    SET INIValue=
     
    :: Reset temporary variables
    SET SectOK=0
    SET SectFound=0
    SET KeyFound=0
     
    :: Search the INI file line by line
    FOR /F "tokens=* delims=" %%A IN ('TYPE %INIFile%') DO CALL :ParseINI "%%A"
     
    :: Display the result
    ECHO.
    :: EXIT /B return codes (errorlevels) added by Van Woods,
    :: US Army Corps of Engineers, Seattle District
    IF NOT %SectFound%==1 (
        ECHO INI section not found
        EXIT /B 1
    ) ELSE (
        IF NOT %KeyFound%==1 (
            ECHO INI key not found
            EXIT /B 2
        ) ELSE (
            IF DEFINED INIValue (
                ECHO.%INIFile%
                ECHO [%INISection%]
                ECHO %INIKey%=%INIValue%
            ) ELSE (
                ECHO Value not defined
                EXIT /B 3
            )
        )
    )
     
    :: Corrected environment variable by Van Woods,
    :: US Army Corps of Engineers, Seattle District
    ENDLOCAL & SET %INIKey%=%INIValue%
    GOTO:EOF
     
     
    :ParseINI
    :: Skip rest of file after key has been found;
    :: speed improvement by Jeroen Verschuuren
    IF "%SectFound%"=="1" IF "%KeyFound%"=="1" GOTO:EOF
    :: Store quoted line in variable
    SET Line="%~1"
     
    :: Check if this line is the required section heading
    ECHO.%Line%| FIND /I "[%INISection%]" >NUL
    IF NOT ERRORLEVEL 1 (
        SET SectOK=1
        SET SectFound=1
        GOTO:EOF
    )
    :: Check if this line is a different section header
    IF "%Line:~1,1%"=="[" SET SectOK=0
    IF %SectOK%==0 GOTO:EOF
     
    :: Parse any "key=value" line
    FOR /F "tokens=1* delims==" %%a IN ('ECHO.%Line%') DO (
        SET Key=%%a^"
        SET Value=^"%%b
    )
     
    :: Strip quotes, tabs, and surrounding spaces from key and value
    :: Modifications added by Van Woods,
    :: US Army Corps of Engineers, Seattle District
    SET Value=%Value:"=%
    :: Remove quotes
    SET Key=%Key:"=%
    :: Remove tabs
    SET Value=%Value:   =%
    SET Key=%Key:   =%
    :: Remove leading spaces
    FOR /F "tokens=* delims= " %%A IN ("%Key%")   DO SET Key=%%A
    FOR /F "tokens=* delims= " %%A IN ("%Value%") DO SET Value=%%A
    :: Remove trailing spaces
    FOR /L %%A in (1,1,32) do if "!Key:~-1!"==" " set Key=!Key:~0,-1!
    FOR /L %%A in (1,1,32) do if "!Value:~-1!"==" " set Value=!Value:~0,-1!
     
    :: Now check if the key matches the required key
    IF /I "%Key%"=="%INIKey%" (
        SET INIValue=%Value%
        SET KeyFound=1
    )
     
    :: End of ParseINI subroutine
    GOTO:EOF
     
     
     
    :Syntax
    ECHO.
    ECHO ReadINI.bat,  Version 1.30 for Windows NT 4 / 2000 / XP / Server 2003
    ECHO Read a value from the specified INI file
    ECHO.
    ECHO Usage:  READINI  "ini_file"  "section"  "key"
    ECHO Where:           "ini_file" is the file name of the INI file to be read
    ECHO                  "section"  is the section name, without the brackets
    ECHO                  "key"      is the key whose value must be read
    ECHO.
    ECHO Example: if MYPROG.INI looks like this:
    ECHO     [Section 1]
    ECHO     Key1=Value 1
    ECHO     Key2=Value 2
    ECHO     [Section 2]
    ECHO     Key2=Value 4
    ECHO Then the command:  READINI "MYPROG.INI" "section 1" "key2"
    ECHO will return:       Key2=Value 2
    ECHO.
    ECHO Written by Rob van der Woude
    ECHO http://www.robvanderwoude.com
    ECHO Speed improvement by Jeroen Verschuuren
    ECHO Return codes, whitespace removal and corrected environment variable
    ECHO by Van Woods, US Army Corps of Engineers, Seattle District


Добавляйте и вы что-нибудь интересное! ;)

Автор: JoeUser 14.10.16, 10:59
Цитата Jin X @
Ещё один пример с задержкой

Задержку по фэншую (в венде) задают в виде пинга в n-повторений.

Автор: Jin X 14.10.16, 11:07
Цитата JoeUser @
Задержку по фэншую (в венде) задают в виде пинга в n-повторений.
Так?
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    ping 127.0.0.1 -n 5 -w 0 > nul
Вариант, конечно, но только если нужна задержка, кратная 1 секунде.
В моём примере точность 10 мс (1/100 сек).

Автор: JoeUser 14.10.16, 19:54
Цитата Jin X @
Так?

Ну да, как-то так

Автор: Jin X 19.10.16, 12:37
M

Продолжение обсуждения задержки и PowerShell вырублено в отдельную тему:
Задержка

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)