Вопрос по – Heredoc для Windows пакетной?

26

Есть ли способ указания многострочных строк в пакетном режиме, аналогичный heredoc в оболочках Unix. Что-то похожее

cat <<EOF > out.txt
bla
bla
..
EOF

Идея состоит в том, чтобы создать пользовательский файл из файла шаблона ..

Ваш Ответ

17   ответов
27

Самое близкое, что я знаю, это

> out.txt (
    @echo.bla
    @echo.bla
    ...
)

(@ запрещает самой командной оболочке печатать команды, которые она выполняет, иecho. позволяет начать строку с пробела.)

Есть ли решение для передачи содержимого в другую команду? Vincent Robert
Вы можете передать другую команду, см. Мой пост ниже. Кредит принадлежит «эпимент» за лучшую технику. Michael Erickson
1

который, на мой взгляд, является лучшим, следующее сделает трубу:

(
    @echo.line1
    @echo.line2 %time% %os%
    @echo.
    @echo.line4
) | more

В посте ephemient он перенаправил в начале, это хороший стиль, но вы также можете перенаправить в конце как таковой:

(
    @echo.line1
    @echo.line2 %time% %os%
    @echo.
    @echo.line4
) >C:\Temp\test.txt

Отметьте, что "@echo." никогда не включается в вывод и "@echo." сам по себе дает пустую строку.

28

Вот другой подход.

@echo off

:: ######################################################
:: ## Heredoc syntax:                                  ##
:: ## call :heredoc uniqueIDX [>outfile] && goto label ##
:: ## contents                                         ##
:: ## contents                                         ##
:: ## contents                                         ##
:: ## etc.                                             ##
:: ## :label                                           ##
:: ##                                                  ##
:: ## Notes:                                           ##
:: ## Variables to be evaluated within the heredoc     ##
:: ## should be called in the delayed expansion style  ##
:: ## (!var! rather than %var%, for instance).         ##
:: ##                                                  ##
:: ## Literal exclamation marks (!) and carats (^)     ##
:: ## must be escaped with a carat (^).                ##
:: ######################################################



:--------------------------------------------
: calling heredoc with results sent to stdout
:--------------------------------------------

call :heredoc stickman && goto next1

\o/
 | This is the "stickman" heredoc, echoed to stdout.
/ \
:next1



:-----------------------------------------------------------------
: calling heredoc containing vars with results sent to a text file
:-----------------------------------------------------------------

set bodyText=Hello world!
set lipsum=Lorem ipsum dolor sit amet, consectetur adipiscing elit.

call :heredoc html >out.txt && goto next2
<html lang="en">
    <body>
        <h3>!bodyText!</h3>
        <p>!lipsum!</p>
    </body>
</html>

Thus endeth the heredoc.  :)
:next2



echo;
echo Does the redirect to a file work?  Press any key to type out.txt and find out.
echo;

pause>NUL
type out.txt
del out.txt

:: End of main script
goto :EOF

:: ########################################
:: ## Here's the heredoc processing code ##
:: ########################################
:heredoc <uniqueIDX>
setlocal enabledelayedexpansion
set go=
for /f "delims=" %%A in ('findstr /n "^" "%~f0"') do (
    set "line=%%A" && set "line=!line:*:=!"
    if defined go (if #!line:~1!==#!go::=! (goto :EOF) else echo(!line!)
    if "!line:~0,13!"=="call :heredoc" (
        for /f "tokens=3 delims=>^ " %%i in ("!line!") do (
            if #%%i==#%1 (
                for /f "tokens=2 delims=&" %%I in ("!line!") do (
                    for /f "tokens=2" %%x in ("%%I") do set "go=%%x"
                )
            )
        )
    )
)
goto :EOF

Пример вывода:

C:\Users\oithelp\Desktop>heredoc

\o/
 | This is the "stickman" heredoc, echoed to stdout.
/ \

Does the redirect to a file work?  Press any key to type out.txt and find out.

<html lang="en">
    <body>
        <h3>Hello world!</h3>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
    </body>
</html>

Thus endeth the heredoc.  :)
Проверьте еще более элегантную реализацию, которая использует PrintHere.bat на Stackoverflow.com / а / 31216893/1012053 dbenham
хороший. Спасибо, что поделилис Amro
+ 1, два небольших улучшения. использоватьecho( вместо тогоecho; иначе это не с строкой, содержащей/?. Уберите номер строки сset "line=!line:*:=!", как с разделителями =: вы также удаляете все ведущие двоеточия jeb
Определенно, это (на мой взгляд) лучшее решение для heredoc в пакетных файлах. Я хотел бы добавить несколько комментариев и предложить некоторые улучшения кода, но режим комментариев не позволяет этого. Если вас заинтересовали мои предложения - смотрите мой пост Stackoverflow.com / а / 29329912/3627676 jsxt
Спасибо, джеб. Выполнена. rojo
18

очень возможно. ^ - буквальный escape-символ, просто поместите его перед новой строкой. В этом примере я также вставил дополнительный символ новой строки, чтобы он правильно печатался в файле:

@echo off
echo foo ^

this is ^

a multiline ^

echo > out.txt

Выход

E:\>type out.txt
foo
 this is
 a multiline
 echo

E:\>
9
@echo off
 for /f "delims=:" %%a in (
     'findstr -n "^___" %0') do set "Line=%%a"

 (for /f "skip=%Line% tokens=* eol=_" %%a in (
       'type %0') do echo(%%a) > out.html
:: out.html
pause
goto: EOF



___DATA___
<!Doctype html>
<html>
  <head>
   title></title>
  </head>
  <body>
    <svg width="900" height="600">
        <text x="230" 
              y="150"
              font-size="100"
              fill="blue"
              stroke="gray"
              stroke-width="1">
                  Hello World              
        </text>
    </svg>
  </body>
</html>
Это отличное начало. Смотреть на Stackoverflow.com / д / 7885437/745412 для более подробной информации о том, как это сделать. Jared
Удивительно, это отлично сработало для меня! Единственное, что мне нужно было сделать, это добавитьSETLOCAL DISABLEDELAYEDEXPANSION передfor loop (в моем выходном файле отсутствовали восклицательные знаки из-за того, что ранее было включено отложенное расширение). Он по-прежнему удаляет пробелы в начале строк выходного файла, но я возьму ег Shoelaced
6

удивительное поведение ошибочного утверждения GOTO в форме(goto) 2>nul. Затем Аасини и Джеб задокументировали некоторые дополнительные интересные открытия о странном поведении. Это в основном ведет себя какEXIT /B, за исключением того, что он позволяет сцепленным командам внутри подпрограммы CALLed выполняться в контексте родительского вызывающег

Вот краткий сценарий, который демонстрирует большинство существенных моментов:

@echo off
setlocal enableDelayedExpansion
set "var=Parent Value"
(
  call :test
  echo This and the following line are not executed
  exit /b
)
:break
echo How did I get here^^!^^!^^!^^!
exit /b

:test
setlocal disableDelayedExpansion
set "var=Child Value"
(goto) 2>nul & echo var=!var! & goto :break
echo This line is not executed

:break
echo This line is not executed

-- ВЫХОД -

var=Parent Value
How did I get here!!!!

Это удивительное поведение позволило мне написать элегантную пакетную эмуляцию здесь документа со многими опциями, доступными для Unix. Я реализовал PrintHere.bat как отдельную утилиту, которую следует поместить в папку, указанную в вашем PATH. Тогда любой пакетный скрипт может легко вызвать утилиту, чтобы получить здесь документацию.

Вот общий синтаксис использования:

call PrintHere :Label
Here doc text goes here
:Label

Как этого можно достичь? ... Моя утилита PrintHere использует(GOTO) 2>nul Трюк дважды.

Первый раз, когда я использую(GOTO) 2>nul, чтобы вернуться к вызывающей стороне, чтобы я мог получить полный путь к вызывающему сценарию, чтобы PrintHere знал, из какого файла читать. Я тогда ВЫЗЫВАЮ ПЕЧАТЬ ЗДЕСЬ второй р

Во второй раз я использую(GOTO) 2>nul чтобы вернуть вызывающему абоненту и GOTO завершающую метку, чтобы текст документа здесь не выполнялся.

Note - приведенный ниже скрипт содержит символ табуляции (0x09) в определении табуляции, прямо под:start этикетка. Некоторые браузеры могут испытывать трудности при отображении и копировании вкладки. В качестве альтернативы вы можетеdownload PrintHere.bat.txt из моего Dropbox и просто переименуйте его в PrintHere.bat.

Я изначально отправил PrintHere.bat в DosTips, где вы можете отслеживать будущее развитие.

PrintHere.bat

@echo off & setlocal disableDelayedExpansion & goto :start
::PrintHere.bat version 1.1 by Dave Benham
:::
:::call PrintHere [/E] [/- "TrimList"] :Label ["%~f0"]
:::call PrintHere [/E] [/- "TrimList"] :Label "%~f0" | someCommand & goto :Label
:::PrintHere /?
:::PrintHere /V
:::
:::  PrintHere.bat provides functionality similar to the unix here doc feature.
:::  It prints all content between the CALL PrintHere :Label line and the
:::  terminating :Label. The :Label must be a valid label supported by GOTO, with
:::  the additional constraint that it not contain *. Lines are printed verbatim,
:::  with the following exceptions and limitations:
:::
:::    - Lines are lmited to 1021 bytes long
:::    - Trailing control characters are stripped from each line
:::
:::  The code should look something like the following:
:::
:::     call PrintHere :Label
:::         Spacing    and blank lines are preserved
:::
:::     Special characters like & < > | ^ ! % are printed normally
:::     :Label
:::
:::  If the /E option is used, then variables between exclamation points are
:::  expanded, and ! and ^ literals must be escaped as ^! and ^^. The limitations
:::  are different when /E is used:
:::
:::    - Lines are limited to ~8191 bytes long
:::    - All characters are preserved, except !variables! are expanded and ^! and
:::      ^^ are transformed into ! and ^
:::
:::  Here is an example using /E:
:::
:::     call PrintHere /E :SubstituteExample
:::       Hello !username!^!
:::     :SubstituteExample
:::
:::  If the /- "TrimList" option is used, then leading "TrimList" characters
:::  are trimmed from the output. The trim characters are case sensitive, and
:::  cannot include a quote. If "TrimList" includes a space, then it must
:::  be the last character in the list.
:::
:::  Multiple PrintHere blocks may be defined within one script, but each
:::  :Label must be unique within the file.
:::
:::  PrintHere must not be used within a parenthesized code block.
:::
:::  Scripts that use PrintHere must use \r\n for line termination, and all lines
:::  output by PrintHere will be terminated by \r\n.
:::
:::  All redirection associated with a PrintHere must appear at the end of the
:::  command. Also, the CALL can include path information:
:::
:::     call "c:\utilities\PrintHere.bat" :MyBlock>test.txt
:::       This line is written to test.txt
:::     :MyBlock
:::
:::  PrintHere may be used with a pipe, but only on the left side, and only
:::  if the source script is included as a 2nd argument, and the right side must
:::  explicitly and unconditionally GOTO the terminating :Label.
:::
:::     call PrintHere :PipedBlock "%~f0" | more & goto :PipedBlock
:::       text goes here
:::     :PipedBlock
:::
:::  Commands concatenated after PrintHere are ignored. For example:
:::
:::     call PrintHere :ignoreConcatenatedCommands & echo This ECHO is ignored
:::       text goes here
:::     :ignoreConcatenatedCommands
:::
:::  PrintHere uses FINDSTR to locate the text block by looking for the
:::  CALL PRINTHERE :LABEL line. The search string length is severely limited
:::  on XP. To minimize the risk of PrintHere failure when running on XP, it is
:::  recommended that PrintHere.bat be placed in a folder included within PATH
:::  so that the utility can be called without path information.
:::
:::  PrintHere /? prints out this documentation.
:::
:::  PrintHere /V prints out the version information
:::
:::  PrintHere.bat was written by Dave Benham. Devlopment history may be traced at:
:::    http://www.dostips.com/forum/viewtopic.php?f=3&t=6537
:::

:start
set "tab=   "   NOTE: This value must be a single tab (0x09), not one or more spaces
set "sp=[ %tab%=,;]"
set "sp+=%sp%%sp%*"
set "opt="
set "/E="
set "/-="

:getOptions
if "%~1" equ "" call :exitErr Invalid call to PrintHere - Missing :Label argument
if "%~1" equ "/?" (
  for /f "tokens=* delims=:" %%L in ('findstr "^:::" "%~f0"') do echo(%%L
  exit /b 0
)
if /i "%~1" equ "/V" (
  for /f "tokens=* delims=:" %%L in ('findstr /rc:"^::PrintHere\.bat version" "%~f0"') do echo(%%L
  exit /b 0
)
if /i %1 equ /E (
  set "/E=1"
  set "opt=%sp+%.*"
  shift /1
  goto :getOptions
)
if /i %1 equ /- (
  set "/-=%~2"
  set "opt=%sp+%.*"
  shift /1
  shift /1
  goto :getOptions
)
echo %1|findstr "^:[^:]" >nul || call :exitErr Invalid PrintHere :Label
if "%~2" equ "" (
  (goto) 2>nul
  setlocal enableDelayedExpansion
  if "!!" equ "" (
    endlocal
    call %0 %* "%%~f0"
  ) else (
    >&2 echo ERROR: PrintHere must be used within a batch script.
    (call)
  )
)
set ^"call=%0^"
set ^"label=%1^"
set "src=%~2"
setlocal enableDelayedExpansion
set "call=!call:\=[\\]!"
set "label=!label:\=[\\]!"
for %%C in (. [ $ ^^ ^") do (
  set "call=!call:%%C=\%%C!"
  set "label=!label:%%C=\%%C!"
)
set "search=!sp!*call!sp+!!call!!opt!!sp+!!label!"
set "cnt="
for /f "delims=:" %%N in ('findstr /brinc:"!search!$" /c:"!search![<>|&!sp:~1!" "!src!"') do if not defined skip set "skip=%%N"
if not defined skip call :exitErr Unable to locate CALL PrintHere %1
for /f "delims=:" %%N in ('findstr /brinc:"!sp!*!label!$" /c:"!sp!*!label!!sp!" "!src!"') do if %%N gtr %skip% if not defined cnt set /a cnt=%%N-skip-1
if not defined cnt call :exitErr PrintHere end label %1 not found
if defined /E (
  for /f "skip=%skip% delims=" %%L in ('findstr /n "^^" "!src!"') do (
    if !cnt! leq 0 goto :break
    set "ln=%%L"
    if not defined /- (echo(!ln:*:=!) else for /f "tokens=1* delims=%/-%" %%A in (^""%/-%!ln:*:=!") do (
      setlocal disableDelayedExpansion
      echo(%%B
      endlocal
    )
    set /a cnt-=1
  )
) else (
  for /l %%N in (1 1 %skip%) do set /p "ln="
  for /l %%N in (1 1 %cnt%) do (
    set "ln="
    set /p "ln="
    if not defined /- (echo(!ln!) else for /f "tokens=1* delims=%/-%" %%A in (^""%/-%!ln!") do (
      setlocal disableDelayedExpansion
      echo(%%B
      endlocal
    )
  )
) <"!src!"
:break
(goto) 2>nul & goto %~1


:exitErr
>&2 echo ERROR: %*
(goto) 2>nul & exit /b 1

олная документация встроена в скрипт. Ниже приведены некоторые примеры использования:

Вербатим выходной

@echo off
call PrintHere :verbatim
    Hello !username!^!
    It is !time! on !date!.
:verbatim

-- ВЫХОД -

    Hello !username!^!
    It is !time! on !date!.


Расширить переменные (отложенное расширение не должно быть включено)

@echo off
call PrintHere /E :Expand
    Hello !username!^!
    It is !time! on !date!.
:Expand

--ВЫХОД-

    Hello Dave!
    It is 20:08:15.35 on Fri 07/03/2015.


Расширить переменные и обрезать начальные пробелы

@echo off
call PrintHere /E /- " " :Expand
    Hello !username!^!
    It is !time! on !date!.
:Expand

--ВЫХОД-

Hello Dave!
It is 20:10:46.09 on Fri 07/03/2015.


Выход может быть перенаправлен в файл

@echo off
call PrintHere :label >helloWorld.bat
  @echo Hello world!
:label


Выход не может быть перенаправлен как вход, но он может быть передан по трубопроводу! К сожалению, синтаксис не так элегантен, потому что обе стороны трубы выполняются в новом процессе CMD.EXE, так(GOTO) 2>nul возвращает дочерний процесс cmd, а не главный сценарий.

@echo off
call PrintHere :label "%~f0" | findstr "^" & goto :label
  Text content goes here
:label
Очень интересно, спасибо. Я не специалист по пакетным играм, поэтому я признаю, что большинство из них - над головой;) Amro
@ Amro - Возможно, слишком сложно понять, как это работает, но вам не нужно понимать, чтобы использовать его ;-) Я разработал утилиту для простоты использования. dbenham
Если вы хотите доставить одну летучую мышь, содержащую PrintHere вместе с основным сценарием, она будет работать с использованием помеченных вызовов, т. Е.call :PrintHere :endLabel? Sam Hasler
@ SamHasler - Да, все работает так, как написано. Вы можете удалить документацию, а затемGOTO :START не нужен. Вы также можете избавиться от@ECHO OFF. dbenham
5

Использование Макро с параметрами позволяет написать "heredoc" более простым способом:

@echo off

rem Definition of heredoc macro
setlocal DisableDelayedExpansion
set LF=^


::Above 2 blank lines are required - do not remove
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
set heredoc=for %%n in (1 2) do if %%n==2 (%\n%
       for /F "tokens=1,2" %%a in ("!argv!") do (%\n%
          if "%%b" equ "" (call :heredoc %%a) else call :heredoc %%a^>%%b%\n%
          endlocal ^& goto %%a%\n%
       )%\n%
    ) else setlocal EnableDelayedExpansion ^& set argv=


rem Heredoc syntax:
rem
rem %%heredoc%% :uniqueLabel [outfile]
rem contents
rem contents
rem ...
rem :uniqueLabel
rem
rem Same notes of rojo's answer apply

rem Example borrowed from rojo's answer:

set bodyText=Hello world!
set lipsum=Lorem ipsum dolor sit amet, consectetur adipiscing elit.

%heredoc% :endHtml out.txt
<html lang="en">
    <body>
        <h3>!bodyText!</h3>
        <p>!lipsum!</p>
    </body>
</html>
:endHtml

echo File created:
type out.txt
del out.txt
goto :EOF


rem Definition of heredoc subroutine

:heredoc label
set "skip="
for /F "delims=:" %%a in ('findstr /N "%1" "%~F0"') do (
   if not defined skip (set skip=%%a) else set /A lines=%%a-skip-1
)
for /F "skip=%skip% delims=" %%a in ('findstr /N "^" "%~F0"') do (
   set "line=%%a"
   echo(!line:*:=!
   set /A lines-=1
   if !lines! == 0 exit /B
)
exit /B
3

@ Джеб

setlocal EnableDelayedExpansion
set LF=^


REM Two empty lines are required

другой вариант:

@echo off

:)
setlocal enabledelayedexpansion
>nul,(pause&set /p LF=&pause&set /p LF=)<%0
set LF=!LF:~0,1!

echo 1!LF!2!LF!3

pause
+ 1, очень приятно видеть альтернативный способ создания LF и эффект команды паузы jeb
3

https: //stackoverflow.com/a/15032476/362767

Определенно, его решение - то, что я ищу в течение небольшого времени (конечно, я мог бы попытаться реализовать что-то подобное этому, но лень продвигает прогресс :)). Одна вещь, которую я хотел бы добавить, - это небольшое улучшение исходного кода. Я думал, что было бы лучше, если бы перенаправление в файл было написано в конце строки. В этом случае линия стартера heredoc может быть более строгой, а ее анализ - более простым.

@echo off

set "hello=Hello world!"
set "lorem=Lorem ipsum dolor sit amet, consectetur adipiscing elit."

call :heredoc HTML & goto :HTML
<html>
<title>!hello!</title>
<body>
<p>Variables in heredoc should be surrounded by the exclamation mark (^!).</p>
<p>!lorem!</p>
<p>Exclamation mark (^!) and caret (^^) MUST be escaped with a caret (^^).</p>
</body>
</html>
:HTML

goto :EOF

:: https://stackoverflow.com/a/15032476/3627676
:heredoc LABEL
setlocal enabledelayedexpansion
set go=
for /f "delims=" %%A in ( '
    findstr /n "^" "%~f0"
' ) do (
    set "line=%%A"
    set "line=!line:*:=!"

    if defined go (
        if /i "!line!" == "!go!" goto :EOF
        echo:!line!
    ) else (
        rem delims are ( ) > & | TAB , ; = SPACE
        for /f "tokens=1-3 delims=()>&| ,;= " %%i in ( "!line!" ) do (
            if /i "%%i %%j %%k" == "call :heredoc %1" (
                set "go=%%k"
                if not "!go:~0,1!" == ":" set "go=:!go!"
            )
        )
    )
)
goto :EOF

Что я предлагаю этим кодом? Давайте рассмотрим

Код Рохо очень строгий:

не допускает использование более одного пробела в строке междуcall а также:heredoccall :heredoc привязан к краю строки (пробелы в начале строки не допускаются) перенаправление в файл разрешено где-то внутри строки (не очень полезно) -

Вещи, которые я предлагаю:

без строгих (более одного пробела в качестве разделителей) перенаправление в файл разрешено только в конце строки (круглые скобки разрешены и необходимы) без липкого кода до края строки

Обновление 1: Улучшения в проверке и выполнении начала heredoc:

Важная команда толькоcall :heredoc LABEL илиcall :heredoc :LABEL. Поэтому после печати содержимого heredoc можно перейти к другой метке, концу скрипта или выполнитьexit /b. удалить неиспользованную и ненужную команду goto: next2

Обновление 2:

Ограничители для внутреннегоfor являются( ) > & | TAB , ; = SPACEПереключатель/I добавлен кif

Обновление 3:

По следующей ссылке вы можете найти полную версию автономного скрипта (встраивание в ваши скрипты доступно)https: //github.com/ildar-shaimordanov/tea-set/blob/master/bin/heredoc.ba

0

C: \> скопировать con out.txt
Это моя первая строка текста.
Это моя последняя строка текста.
^ Z
1 файл (ов) скопирован.

Выход выглядит так:

C: \> введите out.txt
Это моя первая строка текста.
Это моя последняя строка текста.

(скопируйте con + out.txt, введите свой ввод, затем Ctrl-Z и файл будет скопирован)

COPY CON означает «копировать с консоли» (принять пользовательский ввод)

это будет работать с консоли, но как насчет внутри командного файла? Amro
2

поэтому вам не нужно экранировать специальные символы, такие как<>|& только% нужно сбежать.
Это иногда полезно, как создание вывода html.

@echo off
setlocal EnableDelayedExpansion
set LF=^


REM Two empty lines are required
set ^"NL=^^^%LF%%LF%^%LF%%LF%^^"

for /F "tokens=* delims=_" %%a in (^"%NL%
___"One<>&|"%NL%
___"two 100%%"%NL%
___%NL%
___"three "quoted" "%NL%
___"four"%NL%
") DO (
   @echo(%%~a
)

Выхо

One<>&|
two 100%

three "quoted"
four

Я пытаюсь объяснить код. Переменная LF содержит один символ новой строки, переменная NL содержит^<LF><LF>^.
Это можно использовать с расширением в процентах для размещения ОДНОГО символа новой строки и одной каретки в конце строки.

Обычно FOR / F разбивает цитируемый текст на несколько токенов, но только один раз.
Когда я вставляю символы новой строки, цикл FOR также разбивается на несколько строк.
Цитата в первой и последней строке предназначена только для создания правильного синтаксиса для цикла FOR.

В начале любой строки_, поскольку первый символ будет экранирован из многострочного каретки предыдущей строки, а если кавычка является первым символом, он теряет возможность экранирования.
The_ delims используется, так как пробелы или запятые вызывают проблемы с XP (в противном случае фиктивная ошибка XP-Bug пытается получить доступ к файлам мусора).

Каретка в конце строки также только против ошибки XP.

XP-Bug вступает в силу, когда цитируемый текст содержит не цитируемые,;=<space> символ

for /f "tokens=*" %%a in ("a","b","c") do echo %%a
+ 1 спасибо. Мне трудно после этого, дальнейшее объяснение будет с благодарностью .. Amro
2
@echo off
cls
title Drop Bomb
echo/
echo/ creating...
::                                   Creating a batchfile from within a batchfile.
echo @echo off > boom.bat
echo cls      >> boom.bat
echo color F0 >> boom.bat
echo echo/    >> boom.bat
echo echo --- B-O-O-M !!! --- >> boom.bat
echo echo/    >> boom.bat
echo pause    >> boom.bat
echo exit     >> boom.bat
::                                     Now lets set it off
start boom.bat
title That hurt my ears.
cls
echo/
echo - now look what you've done!
pause 
(спасибо, Джастин) InterociterOperator
1

В Microsoft NMake Makefile можно использовать истинуUNIX heredocs, как их просил владелец темы. Например, это явное правило для создания файла Deploy.sed:

Deploy.sed:
    type << >[email protected]
; -*-ini-generic-*-
;
; Deploy.sed -- Self-Extracting Directives
;

[Version]
Class=IEXPRESS
SEDVersion=3
    .
    .
[Strings]
InstallPrompt=Install $(NAME)-$(VERSION).xll to your personal XLSTART directory?
DisplayLicense=H:\prj\prog\XLL\$(NAME)\README.txt
    .
    .
<<

clean:
    -erase /Q Deploy.sed

где << расширяется во временное имя файла, которое NMake создает на лету при выполнении правила. То есть когда Deploy.sed не существует. Приятно то, что переменные NMake тоже расширяются (здесь переменныеНАЗВАНИ а такжеВЕРСИ). Сохранить это как Makefile. Откройте DOS-окно в каталоге Makefile и использовать:

> nmake Deploy.sed

чтобы создать файл, и:

> nmake clean

чтобы убрать это. NMake является частью всех версий Visual Studio C ++, включая Express-редакции.

Я думаю, что это было заменено на основе XML MSBuild Amro
Да, это было. Чтобы ответить на оригинальный вопрос: на самом деле он не очень отличается от GNU make ... но GNU сделал два десятилетия назад. Тем не менее мощный. Andreas Spindler
Ему уже более 20 лет, и, как мне кажется, Microsoft не стала его развивать, так как они отказались от экспорта make-файлов из Visual Studio. GNU make, с другой стороны, стал довольно совершенным и мощным. Makefiles - отличный инструмент для работы в командной строке. Часто они могут заменять сценарии оболочки / пакетные команды. Я использую make-файлы на любой платформе; в Windows Cygwin's GNU make и NMake. Я благодарен, что они все еще отправляют это с тем замком GUI Visual Studio 2010. Andreas Spindler
+ 1 Я всегда хотел выучить NMake. Отличается ли он от обычного GNU Make (у меня установлены Cygwin и MinGW)? Amro
0

что хотел ОП, было чем-то очень конкретным (создание текстового файла с выходными данными), и принятый ответ прекрасно справляется с этой задачей, но представленное решение не очень хорошо работает вне этого конкретного контекста. Например, если я хочу передать многострочный ввод в команду, я не могу использовать( echo ) синтаксис. Вот что получилось для меня.

Предоставьте Perl-скрипт с именем «echolines.pl», состоящий из следующего (для имитации «реальной» программы):

use strict;
use warnings;

while (<>) {
        chomp;
        print qq(<$_>\n);
}

и командный файл с именем «testme.bat», содержащий:

@echo off

set FOO=foo
set BAR=bar
set BAZ=baz

echo %FOO%^
&echo %BAR%^
&echo %BAZ%|perl echolines.pl

running он производит ожидаемый результат:

C:\>testme
<foo>
<bar>
<baz>

Забота с пробелами должна быть предпринята, чтобы гарантировать, что все работает правильно, без пробелов нигде. В частности: каждый конец строки должен быть символом (^), за которым следует новая строка, последующие строки должны начинаться сразу с амперсанда (&), а в последней строке должен быть канал, начинающийся сразу после последнего отправляемого элемента. Невыполнение этого требования приведет к отсутствию параметров или лишним пробелам до и после параметров.

0

@if(0)==(0) echo on
cscript.exe //nologo //E:JScript "%~f0" source1 out.html
start out.html
goto :EOF

[source1]
<!DOCTYPE html>
<html>
  <head>
   title></title>
  </head>
  <body>
    <svg width="900" height="600">
        <text x="230" 
              y="150"
              font-size="100"
              fill="blue"
              stroke="gray"
              stroke-width="1">
                  Hello World              
        </text>
    </svg>
  </body>
</html>
[/source1]

@end

if (WScript.Arguments.length != 2) WScript.Quit();
var tagName = WScript.Arguments(0);
var path    = WScript.Arguments(1);
var startTag = "[" + tagName + "]"
var endTag   = "[/" + tagName + "]"
var fso = new ActiveXObject("Scripting.FileSystemObject");
var file1 = fso.OpenTextFile(WScript.ScriptFullName);
var txt = "";
var found = false;
while (!file1.AtEndOfStream) {
  var line = file1.ReadLine();
  if (!found) {
    if (line.lastIndexOf(startTag, 0) === 0) found = true;
  } else {
    if (line.lastIndexOf(endTag, 0) === 0) break;
    txt += line + "\n";
  }
}
file1.Close();
var file2 = fso.CreateTextFile(path, true, false);
file2.Write(txt);
file2.Close();
0

ть несколько строк в другую программу без фактического создания текстового файла и ввода, перенаправляя его в вашу программу:

(@echo.bla
@echo.bla
) | yourprog.exe

Для быстрого рабочего примера вы можете заменитьyourprog.exe сmore:

(@echo.bla
@echo.bla
) | more

Выход

bla
bla
-4
C:\>more >file.txt
This is line 1 of file
This is line 2 of file
^C

C:\>type file.txt
This is line 1 of file
This is line 2 of file

** В конце будет добавлена пустая строка, но вы можете легко решить эту проблему, просто используя метод copy con:

C:\>copy con file.This is line 1 of file
This is line 2 of file^Z

C:\>type file.txt
This is line 1 of file
This is line 2 of file

Осторожно, где вы вводите ^ C и ^ Z в каждом случае.

Я могу что-то упустить, но не понимаю, как это отвечает на вопрос. Если да, уточните. blm

Похожие вопросы