Секреты командной Строки Windows часть 2.

В продолжении темы Cmd – хаков, опишу еще несколько эффективных приемов работы с командной строкой.

>> Что такое enabledelayedexpansion?

Вообще я не хотел писать об этом, но т.к. в следующем примере это используется и в справке расписано туманно, напишу.

Обычно при использовании переменных в bat/cmd сценариях используется конструкция %переменная%, однако если значение переменной меняется в теле цикла и считывается там же, это может не работать. Например:

for %%i in (1,2,3) do (
    set "var=%%i"
    echo %var%
Rem Не выведет ничего
)

pause

Если запустить этот пример то интерпретатор просто 3 раза выполнит echo без каких то либо параметров. Для того чтобы все работало верно нужно использовать расширенный режим обработки команд. Задается он командой setlocal  с параметром enabledelayedexpansion, а выключается командой endlocal. Приведу пример:

setlocal enabledelayedexpansion

for %%i in (1,2,3) do (
    set "var=%%i"
    echo !var!
Rem Выведет 1,2,3
)

Pause

Теперь все выводится как и задумано. Замечу что переменная в данном случае обрамлена восклицательными знаками (!).

>> Создание динамических переменных в bat-файлах? Легко!

При написании сценариев командной строки, у администраторов, которые, хотя бы немного программировали на других языках программирования (а cmd можно отнести к ним с натяжкой) возникает определенный дискомфорт при обработке  больших массивов данных. Ведь в cmd отсутствуют массивы! Мы можем обойти это ограничение с использованием динамических переменных. Для этого воспользуемся расширенным режимом обработки команд.

Например есть текстовый файл, нам нужно его прочитать и вывести определенные строки на экран, покажу как это сделать при помощи динамических переменных.

Для начала создадим файл greeka.txt  с таким содержимым:

1.Ехал Грека через реку,Видит Грека - в реке рак.

2.Ехал Грека через реку,Видит Грека - в реке рак.

3.Ехал Грека через реку,Видит Грека - в реке рак.

4.Ехал Грека через реку,Видит Грека - в реке рак.

5.Ехал Грека через реку,Видит Грека - в реке рак.

6.Ехал Грека через реку,Видит Грека - в реке рак.

7.Ехал Грека через реку,Видит Грека - в реке рак.

8.Ехал Грека через реку,Видит Грека - в реке рак.

9.Ехал Грека через реку,Видит Грека - в реке рак.

10.Ехал Грека через реку,Видит Грека - в реке рак.

 

Далее, приступим к написанию нашего сценария:

    @echo off

    setlocal enabledelayedexpansion

Включаем режим расширенной обработки команд.

    set i=0

Объявляем вспомогательную переменную.

    for /F "tokens=*" %%a in (greka.txt) do (

Начало цикла  построчного перебора файла.

      set /A i=!i! + 1

Увеличиваем вспомогательный итератор на единицу. 

      set str!i!=%%a

Собственно сама незамысловатая конструкция создания динамических переменных, с именами str1, str2, str3 и так далее.

    )

Проверим как отработал наш сценарий.

Начало цикла 

Echo Это 10 строка... -------^>^> %str10%
Echo +++++++++++++++++++++++++++++++++++++++++++++
Echo +++++++++++++++++++++++++++++++++++++++++++++
Echo ...а  это вторая -------^>^> %str2%
pause

Как видим динамические переменные использовать довольно удобно и легко, они могут помочь вам заменить массивы и добавят гибкости коду.

>> Поиск и замена текста в файлах средствами cmd/bat файла.

Многие администраторы и Power-пользователи линукс, при знакомстве с возможностями cmd, замечают такую досадную деталь, как отсутствие множества утилит для поиска и замены подстрок в  файлах.

Вообще под windows существует множество утилит для обработки строк в файлах, в том числе и портированных с #nix систем (тот же sed и supersed), но мы не ищем легких путей это будет не совсем чисто, т.к. в нужный момент этого всего может не оказаться под рукой.

Возможна ли реализация данной функции на cmd ? Конечно! А поможет нам в этом специальные строки расширения, а точнее конструкция  вида %переменная:A=B%, где переменная- переменная содержащая исходную подстроку, A – подстрока которую ищем, B – подстрока на которую меняем искомую подстроку в строке.

Приступим писать наш код, т.к. он очень похож на тот что выше, особо вдаваться в детали я не буду:

@echo off

setlocal enabledelayedexpansion

rem Собираем параметры командой строки переданной сценарию.
rem Например сценарий запущен "File_str_replace.bat greka.txt Грека Гитлер"
rem %1 = greka.txt %2=Грека %3=Гитлер
Set infile=%1
Set find=%2
Set replace=%3

    @echo off

    setlocal enabledelayedexpansion

    set COUNT=0

    for /F "tokens=* delims=," %%n in (!infile!) do (
    set LINE=%%n

    set TMPR=!LINE:%find%=%replace%!

REM Именно здесь происходит замена текущей строки!

    Echo !TMPR!>>TMP.TXT

REM Добавляем строку к временному файлу
                    )

REM Делаем резервное копирование исходного файла, на случай что что то пойдет не так…

copy %infile% %infile%.bak

REM Заменяем исходный файл временным

move TMP.TXT %infile%

Наш батник для поиска и замены подстрок файла готов. Теперь сгенерируем файл для него, да побольше! Сделаем это тоже батником:

@echo off
for /L %%i in (1,1,100000) do (

echo %%i.Ехал Грека через реку,Видит Грека - в реке рак.Сунул Грека в реку руку,Рак за руку Греку - цап!>>greka.txt
)

Получился файл, забитый поговоркой, размером ~ 10 мегабайт, неплохо для примера…  Запустим Наш сценарий введя в командной строке “File_str_replace.bat greka.txt Грека Гитлер” , для того чтобы заменить все слова Грека на Гитлер. Запустив увидим что через полторы минуты(неплохо для 20-ти летнего консольного мамонта) в нашем файле поговорка заменилась на “Ехал Гитлер через реку,Видит Гитлер - в реке рак.Сунул Гитлер в реку руку,Рак за руку Греку - цап”. Можно усовершенствовать сценарий, и даже прикрутить к ней регулярные выражения, но это уже мелкие технические детали :)

На сегодня пожалуй все, попозже продолжу.

CmdArcanoid "Графическая" игра, средствами командной строки Windows.

Больше года назад, в порядке эксперимента, я написал игру используя исключительно команды cmd.exe. Игрой это назвать сложно, ибо отсутствует интерактивная составляющая, но тем не менее “компьютер” сам с собой играет. Скачать и посмотреть на это можно здесь.

Собственно как это статично выглядит.

Секреты командной строки Windows, часть 1.

К сожалению, благодаря ряду независящих от нас причин, командная оболочка cmd.exe до сих пор не утратила своей актуальности. Многие системные администраторы используют ее для управления своими задачами, при отсутствии на OS других средств, либо в силу привычки. Несмотря свою на простоту, командная строка обладает рядом интересных и неочевидных возможностей. В этом посте я постараюсь рассказать, о некоторых недокументированных либо малоизвестных возможностях командной строки Windows.

>> Beep из bat-файла.

В консоли Windows отсутствует команда заставляющая пищать системный динамик, но существует "недокументированный" символ (•) при выводе которого на экран консоли системный динамик издает звук. Чтобы ввести его нужно в текстовом редакторе набрать "Alt+7". Например: @echo •.

Проблема заключается в том что не все редакторы сохраняют такие символы, а по закону подлости ты оказываешься за компьютером, который, как раз без такового. Но и это можно обойти: запустим cmd.exe и в командной строке наберем @Echo,  нажав комбинацию Ctrl+G или "Alt+7" получим ^G далее перенаправим это все в файл, должно получиться @Echo echo ^G >beep.bat. Файл-пищалка готов.

>> Внутренний вызов команды CALL.

Из справочной документации Microsoft мы знаем, что команда Call - совершает вызов одного пакетного файла из другого, без завершения выполнения первого файла, но мало кому известно что при помощи Call можно перемещаться по внутренним меткам того же cmd/bat файла, подобно команде Goto. @Зачем это нужно, ведь есть goto?" - спросите вы. А затем, что помимо просто перемещения по меткам команда Сall имеет две особенности :

  1. "Умеет" возвращаться к месту своего вызова с помощью специальной метки :EOF.
  2. Умеет передававать значения в "подпрограмму". Поясню на примере:

@echo off

Rem Вызываем подпрогамму

call :SQRT 2

call :SQRT 8

pause

goto :EOF

rem а вот тут уже выходим см. ниже.

rem ***Начало подпрограммы.***

:SQRT

set /a outputval= %1*%1

echo Корень из %1 равен %outputval%.

goto :EOF

rem не выходим, но всего лишь возвращаемся на место за вызовом

rem ***Конец подпрограммы.***

После выполнения данного командного сценария получим такой вывод:

Красиво, не правда ли? Такая незаметная возможность, может сэкономить кучу строк кода, и на время может показаться, что мы программируем на полноценном скриптовом языке.

Да, стоит учесть еще и то что в подпрограмму можно передавать несколько аргументов, тогда обращаться к ним следует так же как и к аргументам командной строки %1, %2, %3 … и далее по порядку.

Символы экранирования в bat-файле.

Что если вам надо вывести  в консоль текст содержащий операторы или спецсиволы?

Например надо вывести: “%TEMP%”. Попробуем ввести в командную строку Echo %TEMP%.

Результат:

 

На консоль вывелось значение переменной %TEMP%. Совсем не то что нам надо…  Для таких случаев и существуют символы экранирования “^” и “%”. Достаточно его подставить перед спецсимволом и интерпретатор поймет что мы хотим вывести именно символ а не строку или выражение.Для проверки создадим батник:

@Echo off
Echo съешь еще этих французских булок да выпей чаю ^
съешь еще этих французских булок да выпей чаю ^
съешь еще этих французских булок да выпей чаю ^
съешь еще этих французских булок да выпей чаю

Echo %%TEMP%%

Pause

Результат:

Как видим все работает и экономия кода на лицо.

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

На сегодня все, продолжение в другом посте.