Форум программистов, компьютерный форум, киберфорум
Наши страницы
Batch (CMD/BAT)
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.85/27: Рейтинг темы: голосов - 27, средняя оценка - 4.85
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
#1

Обсуждение сложных кодов, команд и синтаксиса*

09.04.2013, 01:28. Просмотров 5497. Ответов 55
Метки нет (Все метки)

Тема с повышенным уровнем сложности.

Создана для пояснения непонятных моментов по кодам темы " Тонкости языка, редкие команды и сложные скрипты ",
и любых других сложных конструкций.

Просто задайте вопрос и будем разбирать вместе смысл написанного.
По результатам обсуждения красивый ответ напишем в комментарии к коду.
А отдельные моменты в тему "... заметки особенностей программинга BAT файлов".

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

0
Вложения
Тип файла: txt Замена с учетом спецсимволов.txt (973 байт, 67 просмотров)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.04.2013, 01:28
Ответы с готовыми решениями:

[Debug] Ввод кодов и декомпиляция команд
Доброго вечера, господа-товарищи. Тут такое дело, есть два вопроса, над которым...

Cумма кодов четных символов равна сумме кодов нечетных
Даны два поля edit1 и edit2. и кнопка button1. Нужно чтобы при нажатии на...

Временно отменить добавление команд в очередь команд диалогового окна
Добрый день, уважаемые программисты! Начнём по порядку... Я пишу оконное...

Таблица футбольных команд: Сформировать показатели команд заданного континента
Есть вот такое задание. Рейтинговая таблица футбольных сборных содержит...

Пример какой-нибудь программы на ассемблере с применением логических команд и команд сдвига.
Разработка программ на ассемблере при реализации логических команд и команд...

55
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
09.04.2013, 01:39  [ТС] #2
Итак.

1) много нового использовано в коде:
Цветная роза с использованием только встроенных команд консоли ссылка

Много мы прояснили и узнали нового в темах:
Сломал полосу прокрутки
Цветной вывод в консоли (обсуждение кода розы)
Там еще остались моменты, мне не понятные, позже обсудим:
1) P.S., например, добавьте в строку со Start двойные кавычки (якобы заголовок CMD и все должно отработать нормально), но нет - CMD перезапуститься со старыми настройками реестра. Твик не заработает. Почему так?
2) Остальное напишу в тему: Встраивание ресурсов в бат-файл (еще пару способов).

2) Вопрос от FraidZZ на счет - как работает код:
Получение символов BackSpace (0x08) и Esc (0x27) в переменную ссылка
Вот он (скорректированный мною):
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
:BL.String.CreateDEL_ESC
@echo off
:: Creates two variables with one character DEL=Ascii-08 and ESC=Ascii-27
:: DEL and ESC can be used  with and without DelayedExpansion
setlocal
for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%A in (1) do rem"') do (
  rem ENDLOCAL
  set "DEL=%%a"
  rem set "DEL=%DEL:~0,1%
  set "ESC=%%b"
  goto ext
)
:ext
<nul set /p test=Tes_
<nul set /p test=%DEL%
echo t
А вот оригинал с темы: "http://www.dostips.com/forum/viewtopic.php?&f=3;&t=1733;&start=15"
Bash
1
2
3
4
5
6
7
8
9
10
11
12
:BL.String.CreateDEL_ESC
:: Creates two variables with one character DEL=Ascii-08 and ESC=Ascii-27
:: DEL and ESC can be used  with and without DelayedExpansion
setlocal
for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
  ENDLOCAL
  set "DEL=%%a"
  set "DEL=%DEL:~0,1%
  set "ESC=%%b"
  goto :EOF
)
goto :eof
Детально объяснить сегодня не успею и заранее оговорка - тему на их форуме я не читал.
Вкратце пояснение:
Часть 1. Внутри IN.
Магическая prompt вот что умеет:

Обсуждение сложных кодов, команд и синтаксиса*


Осталось заставить ее вывести такие символы:
Bash
1
prompt #$H#$E#
Вуаля:
Обсуждение сложных кодов, команд и синтаксиса*


Вместо приглашения C:\users\alex теперь #{BS}#{ESC}
Осталось запарсить это по разделителю #

Только вот нужно как то заставить приглашение "попасть" внутрь цикла.
Итак, вспоминаем, чтобы команда отображалась на экране при выполнении, нужно включить эхо: Echo on.
Но в цикл она все равно не попадет. Ведь он обрабатывает только то, что находится в потоках № 1 и >2.
Команда, которую мы выполняем (по сути набираем на клавиатуре или из текста бат-файла) вообще не попадает в поток. См. скрин (команда CD.)
Обсуждение сложных кодов, команд и синтаксиса*

Вспоминаем про то, как ведет себя сам цикл. На скрине выше видно, что он выводит все команды в своем теле вместе с Prompt. Этой пустышкой и пользуемся.

1.1. Конструкция вида for /f ... IN ('"команды"')
Обеспечивает выполнения команды в кавычках целиком (аналог cmd /c "команды"). Т.о. уходим от необходимости экранировать спецсимволы.
Тоже самое используется внутри цикла в Set. Кавычки позволяют присвоить переменной управляющий спецсимвол.

Часть 2. В цикле.
ENDLOCAL я не понял зачем нужен. Ведь все изменения над средой внутри IN были выполнены в отдельном потоке, а поэтому не влияют на текущую среду.
Видимо код вырезан из другого.
Про Set сказал выше. 1-й токен получен. Присвоили {BS}
set "DEL=%DEL:~0,1%" - видимо в некоторых системах между ## находится более 1 символа. У меня на Win7 визуально 1.
В любом случае конструкция будет работать только в таком виде: set "DEL=!DEL:~0,1!". Исправлять не стал.
set "ESC=%%b" - как проверить пока не знаю. Ansi-консоль себе не устанавливал.
А вот для ESC команда ... :~0,1% как раз имеет смысл, ведь вывод у нас такой:
#{BS}#{ESC} Rem
В переменную ESC попадет {ESC} Rem. Нужно выделять первый символ.
Первый goto :EOF мне не понятен. Будет работать как и второй - просто выйдет из батника. Смысл неясен. Если эта функция вызывается из другого BAT, достаточно одного goto :eof
1
Eva Rosalene
T for Trans-
4050 / 1589 / 302
Регистрация: 06.01.2013
Сообщений: 4,179
Завершенные тесты: 2
09.04.2013, 17:32 #3
Цитата Сообщение от Dragokas Посмотреть сообщение
Детально объяснить сегодня не успею и заранее оговорка - тему на их форуме я не читал.
Вкратце пояснение:
Dragokas, СУПЕР
Наконец понял, что там происходит, хотя часть деталей осталась непонятна.
Но с ними, думаю, сам разберусь.
0
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
23.06.2013, 17:33  [ТС] #4
Нашел у CyberMuesli на OSzon-e:
Bash
1
2
3
4
5
6
7
8
9
10
11
::===========================================================================
:StrLen
::===========================================================================
:: %1=VarName (not VALUE), ret !strLen!
set StrLen.S=A!%~1!
set StrLen=0
for /L %%P in (12,-1,0) do (
    set /a "StrLen|=1<<%%P"
    for %%I in (!StrLen!) do if "!StrLen.S:~%%I,1!"=="" set /a "StrLen&=~1<<%%P"
)
goto :eof
Пока не разбирался как работает.
0
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
23.06.2013, 17:35  [ТС] #5
Кто-нибуть знает как запустить цикл посредством команды call ?

Прим. call for /f ... и т.д.
0
Eva Rosalene
T for Trans-
4050 / 1589 / 302
Регистрация: 06.01.2013
Сообщений: 4,179
Завершенные тесты: 2
23.06.2013, 17:53 #6
Цитата Сообщение от Dragokas Посмотреть сообщение
Кто-нибуть знает как запустить цикл посредством команды call ?
Вынести как процедуру. А в чем проблема?

Добавлено через 10 минут
Bash
1
call cmd /c for %A IN (1) DO @(echo.%A)
Добавлено через 2 минуты
Я так понимаю, что так можно обойти ограничение на количество переменных цикла
1
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
23.06.2013, 18:16  [ТС] #7
@FraidZZ, так не пойдет.
Эта конструкция порождает новый процесс, который не наследует и не возвращает окружение:
Bash
1
2
call cmd /c for %%%%A IN (1) DO @(set s=%%%%A)
echo %s%
Цитата Сообщение от FraidZZ Посмотреть сообщение
Вынести как процедуру. А в чем проблема?
Проблема вот в этом:
Цитата Сообщение от Dragokas Посмотреть сообщение
13) Переменную цикла нельзя раскрыть внутри строки модификаторов другого цикла:
for /f %%q in (quote) do for /f "usebackq tokens=1* delims=%%q" %%a in ("%~dp01.txt") do echo %%a%%b
0
Eva Rosalene
T for Trans-
4050 / 1589 / 302
Регистрация: 06.01.2013
Сообщений: 4,179
Завершенные тесты: 2
23.06.2013, 18:29 #8
Эвон о как. Твой пост прояснил мне причину глюков моих скриптов.
Пробуй так:
Bash
1
2
set g=for /f "usebackq tokens=2 delims=%%q" %%a in (4.txt) do (rem)
!g!
0
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
23.06.2013, 18:55  [ТС] #9
@FraidZZ, тут смотри какой прикол:
С !

Bash
1
2
3
4
5
6
SetLocal EnableExtensions EnableDelayedExpansion
 
set tok=2
set g=for /f "tokens=!tok!" %%a in ^("1 2"^) do set s=%%a
!g!
echo %s%
Обсуждение сложных кодов, команд и синтаксиса*


С %

Bash
1
2
3
4
5
6
SetLocal EnableExtensions EnableDelayedExpansion
 
set tok=2
set g=for /f "tokens=!tok!" %%a in ^("1 2"^) do set s=%%a
%g%
echo %s%
Обсуждение сложных кодов, команд и синтаксиса*


А мне то как раз нужно это исполнить внутри другого цикла.
Ну хоть какое-то решение нашли. Можно вынести в подпрограмму. Будет работать.
0
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
24.06.2013, 04:06  [ТС] #10
@FraidZZ, хочешь головоломку?

Я в принципе еще не думал, может решение и простое, и быстрое.

Задача: раскрытие значения переменной неограниченное число раз, скажем 5.
Когда имя переменной состоит из значения другой переменной, имя которой состоит из значения третьей переменной и т.д. ...
What is - описано здесь: Ввести три числа и в зависимости от их порядка запустить три приложения через паузу в 10 секунд

Интересно элегантное решение, а не серия последовательных Set-ов.
Да, задача мной не до конца сформулирована, но можно додумать ее
1
Eva Rosalene
T for Trans-
4050 / 1589 / 302
Регистрация: 06.01.2013
Сообщений: 4,179
Завершенные тесты: 2
24.06.2013, 11:07 #11
Mission Accepted. Доконца проснусь и приступлю.

Добавлено через -3 минут
Bash
1
call call call call set
0
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
11.07.2013, 16:12  [ТС] #12
Появилась новая задачка: Как передать VBS-скрипту из консоли знаки скобок?

Исходный код в этой теме: Вставка текста из VBS в cmd

Описание проблемы и мои попытки видны на скринах:
0
Миниатюры
Обсуждение сложных кодов, команд и синтаксиса*   Обсуждение сложных кодов, команд и синтаксиса*   Обсуждение сложных кодов, команд и синтаксиса*  

sov44
1758 / 742 / 128
Регистрация: 09.04.2011
Сообщений: 1,313
11.07.2013, 16:16 #13
Dragokas, а если через короткие имена?
1
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
11.07.2013, 16:57  [ТС] #14
Прикинь, тоже глотает.

Оказывается глюк связан с получением аргументов через именованные параметры.
Если получать как Wscript.Arguments(0), то все нормально.

Кстати, как получить имя папки Program Files(x86) в формате 8.3 ?
Ать, сам и отвечаю:
Bash
1
for /f "delims=" %%a in ("%programfiles(x86)%") do echo %%~sa
0
Миниатюры
Обсуждение сложных кодов, команд и синтаксиса*   Обсуждение сложных кодов, команд и синтаксиса*  
Smitis
1629 / 338 / 39
Регистрация: 15.10.2012
Сообщений: 529
12.07.2013, 00:13 #15
Dragokas, честно говоря, не понял проблемы.
Visual Basic
1
WScript.Echo WScript.Arguments.Named("param")
запускаю
Bash
1
cscript param.vbs /param:"c:\Program Files (x86)\Internet Explorer\iexplore.exe"
И всё нормально.

Добавлено через 24 минуты
Это sendkeys скобки глотает
Некоторые специальные символы следует всегда задавать заключёнными в фигурные скобки. Перечень таких символов:
{+} {^} {%} {~} {(} {)} {[} {]} {{} {}}
1
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
07.08.2013, 02:15  [ТС] #16
Цитата Сообщение от FraidZZ Посмотреть сообщение
Mission Accepted. Доконца проснусь и приступлю. Добавлено через 3 минуты:
Bash
call call call call set
amel27 привел на счет этого красивый пример. Цитирую:

Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@echo off
 
set "$1=++"
set "$2=$1"
set "$3=$2"
 
set $
pause
 
echo %$3%
echo %%%$3%%%
call echo %%%$3%%%
call echo %%%%%%%$3%%%%%%%
call call echo %%%%%%%$3%%%%%%%
 
pause
результат:

$1=++
$2=$1
$3=$2
Для продолжения нажмите любую клавишу . . .
$2
%$2%
$1
%$1%
++
Для продолжения нажмите любую клавишу . . .
1
Eva Rosalene
T for Trans-
4050 / 1589 / 302
Регистрация: 06.01.2013
Сообщений: 4,179
Завершенные тесты: 2
24.11.2013, 21:45 #17
Пояснение к коду: Считывание файла в переменную с учетом переносов строк

Для ленивых
Bash
1
2
3
4
5
6
7
8
9
10
11
:ReadTo
set _m=^
 
 
 
::Не удаляем пустые строки выше!!!
for /f "usebackq tokens=*" %%A IN (`find /C /V ""^<"%~1"`) DO (set _cn=%%A)
(for /L %%A IN (1 1 !_cn!) DO (set "_fa="&set /p "_fa="&set %~2=!%~2!!_fa!!_m!))<"%~1"
set %~2=!%~2:~0,-1!
(set _cn=&set _fa=&set _m=)
exit /b

Конкретно пояснение требуется к строке №3. Суть данного приема кроется в том, что как только в CMD встречается последовательность символов ^{CR}, парсер воспринимает следующий символ, как продолжение команды, независимо от того каким он является. Получается "экранирование через один символ {CR}", причем первый символ {CR} съедается полностью.[Данная информация - исключительно предположение, но слишком похожее на правду]


Однако, автоматическое раскрытие символов внутри %% не сочетается с ограничением M$ по поводу символов {CR} в переменной. Примечательно, что раскрытие внутри !! проблем не вызывает.[Ну, вы поняли...]
0
Dragokas
Эксперт WindowsАвтор FAQ
16945 / 7030 / 855
Регистрация: 25.12.2011
Сообщений: 10,832
Записей в блоге: 16
24.11.2013, 21:59  [ТС] #18
Цитата Сообщение от FraidZZ Посмотреть сообщение
set %~2=!%~2!!_fa!!_m!
а я понял. Т.е. ты накапливаешь в переменной стрОки, при этом в конец каждой ставишь Cr (кстати, именно Cr, а не CrLf ? )

2. Вопрос: почему нужно именно 3 пустые строки, а не одна?
0
Eva Rosalene
T for Trans-
4050 / 1589 / 302
Регистрация: 06.01.2013
Сообщений: 4,179
Завершенные тесты: 2
24.11.2013, 22:38 #19
Цитата Сообщение от Dragokas Посмотреть сообщение
кстати, именно Cr, а не CrLf ?
Пока не знаю.

Цитата Сообщение от Dragokas Посмотреть сообщение
2. Вопрос: почему нужно именно 3 пустые строки, а не одна?
А вот хз(хочу знать, а не то что вы все подумали). Это рушит мою теорию, но я не сдаюсь %)

Добавлено через 26 секунд
Пустые строки нужно две, я очепятался.
0
Smitis
1629 / 338 / 39
Регистрация: 15.10.2012
Сообщений: 529
25.11.2013, 00:16 #20
Цитата Сообщение от FraidZZ Посмотреть сообщение
Однако, автоматическое раскрытие символов внутри %% не сочетается с ограничением M$ по поводу символов {CR} в переменной. Примечательно, что раскрытие внутри !! проблем не вызывает.[Ну, вы поняли...]
Не, не понял. Что за ограничения?

Разное поведение связано, может быть, с тем, что переменные %% и !! раскрываются в разные моменты времени.

Давно хочу этот процесс связанно описать, поэкспериметрировать для проверки, но никак не соберусь. Но коротко примерно так:

Командный процессор (КП) обрабатывает скрипт некоторыми порциями: считывает очередную строку в некий внутренний буфер. Расскрывает переменные. При необходимости (встретился символ ^ в конце строки, или была открывающая скобка) считывается следующая строка, раскрываются переменные и процесс повторяется, пока не встретится строка с закрывающей скобкой (если была открывающая) и не экранированный конец строки. Тут надо бы выяснить экспериментами, переменные раскрываются построчно или все разом в буфере.
В результате имеем некий буфер, представляющий уже не просто текст, а массив со строками. Скорее всего, строки с ^ в конце просто склеиваются в одну.

Затем текст в этом буфере выполняется. Естественно, переменные %% уже раскрыты. Концы строк CRLF обрезаны (ибо нафиг их там хранить). А переменные !! раскрываются по мере выполнения. Поэтому в цикле в () и надо использовать !!. И понятен фокус, с получением значения переменных после endlocal (переменные будут раскрыты раньше, чем выполнится endlocal). Можно было бы назвать такое статическим (для %%) и динамическим (для !!) раскрытием перменных ("отложенное расширение переменных среды" звучит очень уж непонятно, имхо).

В данном случае, при раскрытии переменных с CRLF КП просто натыкается на конец строки там, где по логике скрипта его быть не должно. А после раскрытия !! это уже обычные символы.

Такая вот теория...
2
25.11.2013, 00:16
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.11.2013, 00:16

Группа команд пересылки и арифметико-логических команд
Помогите, какие способы адресации есть у 1 и 2 группы команд? (не менее 8, но...

Даны список футбольных команд высшей лиги России и количество очков, набранных каждой командной в чемпионате России. Известно, что нет команд с равным
Даны список футбольных команд высшей лиги России и количество очков, набранных...

Сформировать одномерный массив из сумм кодов каждой строки и одномерный массив из сумм кодов каждого столбца символьной матрицы
Ввести символьную матрицу 5х7. Сформировать одномерный массив из сумм кодов...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru