В продолжении темы 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-ти летнего консольного мамонта) в нашем файле поговорка заменилась на “Ехал Гитлер через реку,Видит Гитлер - в реке рак.Сунул Гитлер в реку руку,Рак за руку Греку - цап”. Можно усовершенствовать сценарий, и даже прикрутить к ней регулярные выражения, но это уже мелкие технические детали :)
На сегодня пожалуй все, попозже продолжу.