<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Серый форум &mdash; CMD/BAT: Пакетные макросы с параметрами]]></title>
		<link>https://forum.script-coding.com/viewtopic.php?id=9082</link>
		<atom:link href="https://forum.script-coding.com/extern.php?action=feed&amp;tid=9082&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «CMD/BAT: Пакетные макросы с параметрами».]]></description>
		<lastBuildDate>Tue, 31 Dec 2013 14:07:03 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Re: CMD/BAT: Пакетные макросы с параметрами]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=78716#p78716</link>
			<description><![CDATA[<p>Ах, да! </p><p>3. Параметры подпрограммам передаются через позиционные переменные вида %1, %2, ... %9. Параметры в макросы передаются с помощью позоционных переменных вида %%a, %%b, ... %%z. <br />4. Вызов подпрограмм и передача параметров осуществляются с помощью команжы <strong>call :метка аргументы</strong>. Вызов макроса осущетсвляется с помощью команды <strong>%имя_макроса%</strong>. Вызов макроса и передача параметров осуществляется с помощью команды <strong>%macro.call% ( &quot;параметры: ) %имя_макроса%</strong>.</p>]]></description>
			<author><![CDATA[null@example.com (Rumata)]]></author>
			<pubDate>Tue, 31 Dec 2013 14:07:03 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=78716#p78716</guid>
		</item>
		<item>
			<title><![CDATA[Re: CMD/BAT: Пакетные макросы с параметрами]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=78715#p78715</link>
			<description><![CDATA[<div class="quotebox"><cite>Rumata пишет:</cite><blockquote><p>Надо бы уточнить, что значит &quot;независимые переменные&quot;.</p></blockquote></div><p>Вот это имелось в виду: <a href="http://forum.script-coding.com/viewtopic.php?id=2944">CMD/BAT: возврат значений из процедур через параметры</a>. Независимые внутренние переменные и возможность возвращать значения из процедуры (через имя процедуры или имена переданных параметрами переменных окружения).</p>]]></description>
			<author><![CDATA[null@example.com (alexii)]]></author>
			<pubDate>Tue, 31 Dec 2013 13:55:05 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=78715#p78715</guid>
		</item>
		<item>
			<title><![CDATA[Re: CMD/BAT: Пакетные макросы с параметрами]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=78699#p78699</link>
			<description><![CDATA[<div class="quotebox"><cite>alexii пишет:</cite><blockquote><p>А в макросах можно использовать а) независимые переменные окружения и б) возврат значений, как это можно сделать в процедурах?</p></blockquote></div><p>Надо бы уточнить, что значит &quot;независимые переменные&quot;. Верно ли я понимаю, что Вы подразумеваете переменные, имена которых не пересекаются с именами основной программы? Другими словами, нет ограничений на именование переменных внутри макросов?</p><p>Посмотрите примеры в моем сообщении. Там есть ответы на Ваши вопросы. </p><p>В случае с независимыми переменными (так как я понял Вас) работает пара команд setlocal/endlocal. <br />Макросы могут возвращать значения. </p><p>Вообще-то если Вы будете следовать неким общим требованиям, то макросы будут мало чем отличаться от подпрограмм. Например, <br />1. любой повторно используемый код должен использовать команды setlocal/endlocal для локализации переменных окружения<br />2. подпрограммы и макросы могут принимать в качестве необязательного параметра имя внешней (по отношению к вызываемому объекту) переменной для передачи вызывающей программе результата выполнения.</p>]]></description>
			<author><![CDATA[null@example.com (Rumata)]]></author>
			<pubDate>Tue, 31 Dec 2013 06:42:52 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=78699#p78699</guid>
		</item>
		<item>
			<title><![CDATA[Re: CMD/BAT: Пакетные макросы с параметрами]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=78697#p78697</link>
			<description><![CDATA[<p>Английский форум не читал — много непонятных букв.<br />Как я сам понимаю, для того, чтобы макросу можно было передавать параметр, макрос на самом деле надо разделить на две макроподстановки («голову» и «хвост») и уже фактическое значение параметра записывать между ними, но это удобно, если параметр один. Если несколько, то, чтобы не разбивать макрос на n+1 составляющую, надо уже ухищряться, напрмер, использовать цикл (FOR /F &quot;TOKENS=…&quot;?) для разбора списка параметров. — Да, присмотрелся к третьему примеру — так оно и есть, причём FOR/F… вынесено в однотипную для всех макросов «голову», «хвост» — тело цикла — основная рабочая часть макроса, переменные цикла — формальные параметры… Но так можно передавать только строки, не содержащие пробелов, и кавычки здесь не помогут. Хотя параметром может быть и имя переменной: в самом имени пробелов нет, а в её значении — есть… — Опять я, кажется, угадал.</p><div class="quotebox"><cite>alexii пишет:</cite><blockquote><p>А в макросах можно использовать а) независимые переменные окружения</p></blockquote></div><p>Вероятно через CALL, если я понял вопрос:<br /></p><div class="codebox"><pre><code>setlocal enabledelayedexpansion

set macro=call echo Hello, %%username%%^^^^^^^^^^!
%macro%
set username=misha
%macro%
echo:
set &quot;macro=call echo Hello, %%username%%^^^^^!&quot;
%macro%
set username=vasya
%macro%
echo:
set macro=echo Hello, ^^^!username^^^!^^^^^^^^^^!
%macro%
set username=petya
%macro%
echo:
set &quot;macro=echo Hello, ^!username^!^^^^^!&quot;
%macro%
set username=sasha
%macro%
</code></pre></div><div class="quotebox"><cite>alexii пишет:</cite><blockquote><p>б) возврат значений, как это можно сделать в процедурах?</p></blockquote></div><p>Ну, вроде бы, в третьем и четвёртом примерах задуман возврат значения через переменную <em>%STRLEN%</em>, но в третьем он что-то он не работает, а четвёртый возвращает:<br /></p><div class="quotebox"><blockquote><p>STRING=hello, world! from macro<br />STRLEN=24</p></blockquote></div>]]></description>
			<author><![CDATA[null@example.com (wisgest)]]></author>
			<pubDate>Tue, 31 Dec 2013 02:52:42 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=78697#p78697</guid>
		</item>
		<item>
			<title><![CDATA[Re: CMD/BAT: Пакетные макросы с параметрами]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=78684#p78684</link>
			<description><![CDATA[<p>А в макросах можно использовать а) независимые переменные окружения и б) возврат значений, как это можно сделать в процедурах?</p>]]></description>
			<author><![CDATA[null@example.com (alexii)]]></author>
			<pubDate>Mon, 30 Dec 2013 23:16:39 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=78684#p78684</guid>
		</item>
		<item>
			<title><![CDATA[CMD/BAT: Пакетные макросы с параметрами]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=78566#p78566</link>
			<description><![CDATA[<p>С некоторого времени стал почитывать ресурс dostips.com. Наткнулся на интересное решение, выведенное в название темы. </p><p>Существует два способа использования повторяющего кода<br />1. Подпрограмма<br />2. Макрос</p><p>Макрос быстрее так как отсутствуют накладные расходы на (чаще всего) передачу параметров и (всегда) вызов подпрограммы. Тем не менее, использовать макросы в компилируемых языках надо с осторожностью, так как это приводит к увеличению размера программы. Однако это несущественно в языках интерпретируемых. </p><p>По этой ссылке <a href="http://www.dostips.com/forum/viewtopic.php?p=8697#p8697">Batch &quot;macros&quot; with arguments - Major Update</a> приведена наиболее завершенная реализация макросов. Вообще, интересно почитать все обсуждение (5 страниц). Там много текста и очень много кода, однако если удалить все неплохие &quot;красивости&quot; и оставить только самое главное получится следующее.</p><p>Макрос в пакетном сценарии это переменная коружения:<br /></p><div class="codebox"><pre><code>
set &quot;my_macro=echo Hello, world!&quot;

%my_macro%
%my_macro%
</code></pre></div><p>И так, один макрос - множество вызовов. Но более сложные и полезные макросы писать сложнее. </p><p>Для начала рассмотрим подпрограмму <a href="http://forum.script-coding.com/viewtopic.php?pid=70999#p70999">CMD/BAT: Нахождение длины строки</a>. Здесь все относительно просто: есть метка, куда осушествляется вызов, запоминается текущее положение, исполняется код, затем возврат на текущее положение<br /></p><div class="codebox"><pre><code>
@echo off
setlocal

set &quot;STRING=hello, world! from function&quot;
call :strlen STRING STRLEN
set STR

endlocal
goto :EOF


:: call :strlen STRVAR [STRLEN]
:strlen
    setlocal enabledelayedexpansion
    set &quot;str=A!%~1!&quot;
    set &quot;len=0&quot;
    for /l %%A in (12,-1,0) do (
        set /a &quot;len|=1&lt;&lt;%%A&quot;
        for %%B in (!len!) do if &quot;!str:~%%B,1!&quot;==&quot;&quot; set /a &quot;len&amp;=~1&lt;&lt;%%A&quot;
    )
    for %%v in (!len!) do endlocal &amp; if &quot;%~2&quot; neq &quot;&quot; (set %~2=%%v) else (echo:%%v)
goto :EOF
</code></pre></div><p>Чтобы перевести этот код в макрос требуется существенно дописать. Обратите внимание, как производится конкатенация строк кода, так чтобы сохранить прежнее форматирование и правильность кода:<br /></p><div class="codebox"><pre><code>
@echo off
setlocal

:: макрос, который позволяет передавать параметры вызываемым макросам
set macro.call=for /f &quot;tokens=1-26&quot; %%a in

:: макрос вычисления длины строки
set macro.strlen=do (^
    setlocal enableDelayedExpansion^
    ^&amp; set &quot;str=A!%%~a!&quot;^
    ^&amp; set &quot;len=0&quot;^
    ^&amp; ( for /l %%A in (12,-1,0) do^
        set /a &quot;len|=1&lt;&lt;%%A&quot;^
        ^&amp; for %%B in (!len!) do if &quot;!str:~%%B,1!&quot;==&quot;&quot; set /a &quot;len&amp;=~1&lt;&lt;%%A&quot;^
    )^
    ^&amp;(for %%v in (!len!) do endlocal^&amp;if &quot;%%~b&quot; neq &quot;&quot; (set %%~b=%%v) else (echo:%%v)^
)

set &quot;STRING=hello, world! from macro&quot;
%macro.call% ( &quot;STRING STRLEN&quot; ) %macro.strlen%
set STR

endlocal
goto :EOF
</code></pre></div><p>Коллеги в том обсуждении пошли чуть дальше и добавили немного синтаксическогосахара. Кажется так горяздо лучше - достаточно позаботиться о том, чтобы в конце каждой строки присутствовал макрос <strong>%\n%</strong>. Но необходимо не забывать об экранировании спец.символов: &amp;, |, &lt;, &gt;. <br /></p><div class="codebox"><pre><code>
@echo off
setlocal

:: Определяет переменную ВОЗВРАТ КАРЕТКИ (используется как !CR!)
for /f %%a in (&#039;copy /Z &quot;%~dpf0&quot; nul&#039;) do set &quot;CR=%%a&quot;

:: Определяет переменную ПЕРЕВОД СТРОКИ (используется как !LF!)
set LF=^


:: Две пустые строки сверху важны - не удалять!

:: ПЕРЕВОД СТРОКИ, который может использоваться как %xLF%
set ^&quot;xLF=^^^%LF%%LF%^%LF%%LF%&quot;

:: Определяет новую строку с продолжением строки
set ^&quot;\n=^^^%LF%%LF%^%LF%%LF%^^&quot;

:: макрос, который позволяет передавать параметры вызываемым макросам
set macro.call=for /f &quot;tokens=1-26&quot; %%a in

:: макрос вычисления длины строки
set macro.strlen=do (%\n%
    setlocal enabledelayedexpansion%\n%
    set &quot;str=A!%%~a!&quot;%\n%
    set &quot;len=0&quot;%\n%
    for /l %%A in (12,-1,0) do (%\n%
        set /a &quot;len|=1&lt;&lt;%%A&quot;%\n%
        for %%B in (!len!) do if &quot;!str:~%%B,1!&quot;==&quot;&quot; set /a &quot;len&amp;=~1&lt;&lt;%%A&quot;%\n%
    )%\n%
    for %%v in (!len!) do endlocal ^&amp; if &quot;%%~b&quot; neq &quot;&quot; (set %%~b=%%v) else (echo:%%v)%\n%
)

set &quot;STRING=hello, world! from macro&quot;
%macro.call% ( &quot;STRING STRLEN&quot; ) %macro.strlen%
set STR

endlocal
goto :EOF
</code></pre></div><p>Личное мнение - красиво, но сложно для использования в большинстве сценариев. Но может быть весьма полезна там, где требуется скорость. Но стоит ли для этого использовать интерпретатор? </p><p>Хотя коллега с того форума написал на чистом dos shell <a href="http://www.dostips.com/forum/viewtopic.php?f=3&amp;t=4741">игру Змейка</a>, используя описанную здесь технологию.</p>]]></description>
			<author><![CDATA[null@example.com (Rumata)]]></author>
			<pubDate>Fri, 27 Dec 2013 17:45:42 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=78566#p78566</guid>
		</item>
	</channel>
</rss>
