heredoc para Windows lote?

Hay una manera de especificar varias líneas cadenas en lotes de una manera similar a heredoc en unix, shells. Algo similar a:

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

La idea es crear un archivo personalizado a partir de un archivo de plantilla..

InformationsquelleAutor Amro | 2009-06-18

18 Kommentare

  1. 30

    No que yo sepa.

    El más cercano que conozco es

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

    (@ impide que el shell de comandos de sí mismo a partir de la impresión de los comandos que se ejecuta, y echo. permite iniciar una línea con un espacio.)

    • Se puede canalizar a otro comando, por favor ver mi post de abajo. El crédito pertenece a «ephemient» para la mejor técnica, aunque.
  2. 30

    He aquí otro enfoque.

    @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
    

    Ejemplo de salida:

    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.  :)
    
    • +1, Dos pequeñas mejoras. uso echo( en lugar de echo; demás falla con una línea que contiene /?. Tira el número de la línea con set "line=!line:*:=!", como con delims=: quitar también a todos los principales puntos
    • Gracias a jeb. Implementado.
    • Definitivamente, este es (en mi opinión) la mejor solución para heredoc en archivos de proceso por lotes. Me gustaría añadir algunos comentarios y sugerir algunas mejoras en el código, pero el comentario de modo de no permitir esto. Si usted está interesado en mi sugerencias para ver mi post stackoverflow.com/a/29329912/3627676
    • Echa un vistazo a una aún más elegante en la aplicación que utiliza PrintHere.el bate en stackoverflow.com/a/31216893/1012053
  3. 19

    Sí, es muy posible. ^ es el carácter de escape literales, acaba de poner antes de su nueva línea. En este ejemplo, he puesto el salto de línea adicional en como de bien para que quede correctamente impreso en el archivo:

    @echo off
    echo foo ^
    
    this is ^
    
    a multiline ^
    
    echo > out.txt
    

    De salida:

    E:\>type out.txt
    foo
     this is
     a multiline
     echo
    
    E:\>
    
  4. 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>
    
    • Este es un gran comienzo. La mirada en stackoverflow.com/q/7885437/745412 para obtener más detalles sobre cómo hacer esto.
    • Increíble, esto funcionó muy bien para mí! El único retoque que tenía que hacer era agregar SETLOCAL DISABLEDELAYEDEXPANSION antes de la for de bucle (de mi archivo de salida fue la falta de signos de exclamación en cuenta de tener habilitada la expansión retardada anterior). Todavía elimina los espacios en blanco al comienzo de las líneas en el archivo de salida, pero me quedo con ella.
  5. 6

    Más en DosTips, siberia-hombre publicado una demostración de increíble el comportamiento de un error de instrucción GOTO en la forma de (goto) 2>nul. Aacini y jeb, a continuación, documentado algunos adicionales interesantes descubrimientos sobre el comportamiento extraño. Básicamente se comporta como un EXIT /B, excepto que se permite la concatenación de comandos dentro de una Llamada de rutina a ejecutar en el contexto de los padres de llamada.

    Aquí es una breve secuencia de comandos que muestra la mayoría de los puntos sobresalientes:

    @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
    

    — OUTPUT —

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

    Este sorprendente comportamiento me ha permitido escribir un elegante lote de emulación de aquí doc con muchas de las opciones disponibles para unix. He implementado PrintHere.bate como una utilidad independiente que debe ser colocado en una carpeta que aparece en su CAMINO. Entonces cualquier secuencia de comandos por lotes puede LLAMAR fácilmente la utilidad para llegar aquí doc funcionalidad.

    Aquí es la sintaxis general de uso:

    call PrintHere :Label
    Here doc text goes here
    :Label
    

    Cómo puede ser esto posible?… Mi PrintHere utilidad utiliza el (GOTO) 2>nul truco dos veces.

    • La primera vez que uso (GOTO) 2>nul para volver a la llamada para que yo pueda obtener la ruta de acceso completa a la llamada del script para que PrintHere sabe qué archivo para leer. Luego los llamo PrintHere por segunda vez!

    • La segunda vez que uso (GOTO) 2>nul para volver a la llamada y PASAR a la terminación de etiqueta, de modo que aquí el doc de texto no se ejecuta.

    Nota – la siguiente secuencia de comandos contiene un carácter de tabulación (0x09) en la definición de la ficha, directamente debajo de la :start etiqueta. Algunos navegadores pueden tener dificultades para la visualización y la copia de la ficha. Como alternativa, puede descargar PrintHere.bat.txt desde mi dropbox, y simplemente cambiarle el nombre a PrintHere.bate.

    Originalmente publicado PrintHere.el bate en DosTips, donde se puede seguir el desarrollo futuro.

    PrintHere.bate

    @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
    

    Documentación completa está incrustado dentro de la secuencia de comandos. A continuación están algunas demostraciones de uso:

    Verbatim salida

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

    — OUTPUT —

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

    Ampliar variables (retraso en la expansión de la necesidad de no estar habilitado)

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

    –OUTPUT–

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

    Ampliar variables y recortar los espacios iniciales

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

    –OUTPUT–

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

    Salida puede ser redirigida a un archivo

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

    La salida no puede ser redirigido como entrada, pero puede ser canalizada! Por desgracia, la sintaxis no es tan elegante porque ambos lados de una tubería se ejecutan en una nueva CMD.EXE proceso de, así (GOTO) 2>nul devuelve a un niño cmd proceso, y no la secuencia maestra.

    @echo off
    call PrintHere :label "%~f0" | findstr "^" & goto :label
      Text content goes here
    :label
    
    • muy interesante, gracias. Yo no soy un lote de expertos, así que tengo que admitir que la mayoría de es manera por encima de mi cabeza 😉
    • Tal vez demasiado complicado de entender cómo funciona, pero usted no tiene que entender que para hacer uso de ella 😉 he diseñado la utilidad para la facilidad de uso.
    • Si quieres entregar un solo murciélago contiene PrintHere junto con el script principal, va a trabajar el uso de la etiqueta de llamadas, es decir,call :PrintHere :endLabel?
    • Sí que funciona bien como está escrito. Es posible que desee eliminar de la documentación y, a continuación, el GOTO :START no es necesario. También puede deshacerse de la @ECHO OFF.
  6. 5

    El uso de un macros con parámetros permite escribir un «heredoc» de una manera más sencilla:

    @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
    
  7. 3

    @jeb

    setlocal EnableDelayedExpansion
    set LF=^
    
    
    REM Two empty lines are required
    

    otra variante:

    @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, muy agradable ver a una forma alternativa de crear un LF y el efecto del comando de pausa
  8. 3

    Refiriéndose a rojo del post en https://stackoverflow.com/a/15032476/3627676

    Sin duda, su solución es lo que estoy buscando unos de tiempo (por supuesto, yo podría tratar de implementar algo similar a esto, pero la pereza se mueve progreso :)). Una cosa que me gustaría agregar es una pequeña mejora para el código original. Pensé que sería mejor si la redirección a un archivo, fue escrito al final de la línea. En este caso, el heredoc de arranque de la línea podría ser más estrictos y su análisis más simple.

    @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
    

    Lo que estoy sugiriendo por este código? Vamos a considerar.

    Rojo del código es muy estricto:

    • no permite más de un espacio en blanco char en la cadena entre call y :heredoc
    • call :heredoc es pegajoso al borde de la línea (no permitido en los espacios en blanco al principio de la línea)
    • redirección a archivo está permitido en algún lugar dentro de la línea (no muy útil) –

    Cosas de las que estoy sugiriendo:

    • menos estrictos (más de uno de los espacios en blanco como separadores)
    • redirección a archivo permite al final de la línea (redondeado soportes son permitidos y necesario)
    • no pegajosa código para el borde de la línea

    Actualización de 1:
    Mejoras para la comprobación y realización de la heredoc comienzo:

    • importante comando sólo está call :heredoc LABEL o call :heredoc :LABEL. Así que después de la impresión de la heredoc contenido es posible saltar a otra etiqueta, el final de la secuencia de comandos o ejecutar exit /b.
    • quitado no utilizados e innecesarios comando goto :next2

    Actualización 2:

    • Delimitadores para interior for son ( ) > & | TAB , ; = SPACE
    • El interruptor /I añadido a if

    Actualización 3:

    Por el siguiente enlace puede encontrar la versión completa de la secuencia de comandos independiente (incrustación en las secuencias de comandos está disponible) https://github.com/ildar-shaimordanov/tea-set/blob/master/bin/heredoc.bat

  9. 2

    Puede crear un citado bloque de texto con un FOR /F bucle, así que usted no necesita para escapar caracteres especiales como <>|& sólo % tiene que ser escapado.

    Esto a veces es útil como la creación de una salida 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
    )
    

    Salida

    One<>&|
    two 100%
    
    three "quoted"
    four
    

    Trato de explicar el código.
    El LF variable contiene un carácter de nueva línea, el NL variable contiene ^<LF><LF>^.

    Esto puede ser usado con el porcentaje de expansión para colocar UN carácter de salto de línea y un carácter de intercalación en el extremo de la línea.

    Normalmente un FOR /F dividir un texto citado en varios tokens, pero sólo una vez.

    Como puedo insertar caracteres de nueva línea en el bucle también se divide en varias líneas.

    La cita en la primera y en la última línea son sólo para crear la sintaxis correcta para la FOR-loop.

    Al frente de cualquier línea son _ como el primer carácter será escapado de la línea multi cursor de la línea anterior, y si la cita es el primer carácter se pierde al escapar de capacidad.

    El _ delims se utiliza, como espacios o comas causa problemas con XP (otra Cosa que el XP-Error falsos intenta acceder a la basura los nombres de archivo).

    El símbolo de intercalación en el extremo de la línea es sólo contra el XP-Error.

    El XP-Error viene en efecto, cuando un texto citado contiene no cotizados ,;=<space> personajes

    for /f "tokens=*" %%a in ("a","b","c") do echo %%a
    
    • +1 gracias. Estoy teniendo un momento difícil después de esto, otra explicación sería muy apreciada..
  10. 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 
    
  11. 2

    Expansión en ephemient post, que creo que es la mejor, lo siguiente será hacer una pipa:

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

    En ephemient el post de él redirigido al principio, que es un buen estilo, pero también puede redirigir al final como tal:

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

    Nota que «@echo.» es que nunca se incluye en la salida y «@echo.» por sí mismo da una línea en blanco.

  12. 1

    En un NMake de Microsoft makefile uno puede utilizar verdadero UNIX heredocs, como el hilo de titular solicitado. Por ejemplo, esta es una regla explícita para crear un archivo Implementar.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
    

    donde << se expande en un nombre temporal NMake crea sobre la marcha cuando la ejecución de la regla. Es decir, cuando Implementar.sed no existe. Lo bueno es que NMake variables se expanden demasiado (aquí las variables NOMBRE y VERSIÓN). Guardar esto como makefile. Abrir una ventana ms-DOS en el directorio de makefile y uso:

    > nmake Deploy.sed
    

    para crear el archivo, y:

    > nmake clean
    

    para quitarlo. NMake es parte de todas las versiones de Visual Studio C++, incluyendo el Express-ediciones.

    • +1 yo siempre quise aprender NMake. Es muy diferente de regular GNU Hacer (tengo Cygwin y MinGW instalado)?
    • Es 20+ años de edad, y a mí me parece, Microsoft no se ha desarrollado mucho más allá, ya que se dio hasta la exportación de los makefiles de Visual Studio. GNU make por otro lado se ha vuelto bastante perfecto y poderoso. Makefiles son una gran herramienta de trabajo en la línea de comandos. Oftenly se pueden reemplazar secuencias de comandos shell/comandos por lotes. Yo uso makefiles en cualquier plataforma; Cygwin en Windows GNU hacer y NMake. Estoy agradecido de que se sigue de la nave con la GUI castillo de Visual Studio 2010.
    • Creo que fue sustituido por el basado en XML MSBuild
    • Sí, era él. Para responder a la pregunta original: ¿es realmente no es muy diferente de GNU hacer… pero el make de GNU hace dos décadas. No obstante potente.
  13. 1

    Esta es una variante de ephemient excelente solución. Esto le permite tubo varias líneas en otro programa sin que en realidad la creación de un archivo de texto de entrada y redirigirla a su programa:

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

    Para un rápido, ejemplo de trabajo, usted puede reemplazar yourprog.exe con more:

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

    De salida:

    bla
    bla
    
  14. 0

    Lo que el OP quería era algo muy específico (la creación de un archivo de texto con el de salida) y la aceptación de la respuesta hace que la perfección, pero la solución presentada no funciona bien fuera de ese contexto específico. Por ejemplo, si quiero pasar multi-entrada de línea en un comando, no puedo usar el ( echo ) sintaxis. He aquí lo que terminó trabajando para mí.

    Dado un script en perl llamado «echolines.pl» que consta de los siguientes (para simular un ‘real’ del programa):

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

    y un archivo por lotes denominado «testme.murciélago», que contiene:

    @echo off
    
    set FOO=foo
    set BAR=bar
    set BAZ=baz
    
    echo %FOO%^
    &echo %BAR%^
    &echo %BAZ%|perl echolines.pl
    

    ejecución se produce la salida esperada:

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

    Cuidado con los espacios en blanco deben ser tomadas para asegurar que todo funciona correctamente sin perdida de espacios en cualquier lugar. En concreto: cada final de línea debe ser un símbolo de intercalación ( ^ ), seguido por un salto de línea, la línea subsiguiente debe comenzar de inmediato con el carácter ampersand (&) y la última línea debe tener la tubería de comenzar inmediatamente después de que el último elemento para ser enviado. En caso contrario, se producirá una pérdida de parámetros o extra espacios en blanco antes y después de los parámetros.

  15. 0

    Prueba este código. (Código de JScript en la parte inferior escribe «out.html» en el disco)

    @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();
    
  16. 0

    En un apuro, puedo usar el siguiente método (que no disminuye a otros métodos, esto es sólo una preferencia personal):

    Puedo utilizar un bucle a través de un conjunto de cadenas:

    for %%l in (
        "This is my"
        "multi-line here document"
        "that this batch file"
        "will print!"
        ) do echo.%%~l >> here.txt
    
    • No requiere de una subrutina, fácil de recordar y ejecutar.
    • No requiere un archivo temporal.
    • Funciona dentro de una secuencia de comandos por lotes.
    • Trabaja con variables incrustadas.
    • Sin embargo: si usted tiene comillas dobles en sus líneas, el método ya no funciona…

    Aquí es otro ejemplo práctico de la escritura, actualmente estoy trabajando en:

    :intc_version:
    for %%l in (
        "File         : %_SCRIPT_NAME%"
        "Version      : %_VERSION%"
        "Company      : %_COMPANY%"
        "License      : %_LICENSE%"
        "Description  : %_DESCRIPTION%"
        ""
    ) do echo.%%~l
    exit /B 0
    
  17. -1

    Esto es aún más fácil, y se asemeja a cat << EF > out.txt:

    C:\>copia con out.txt

    Este es mi primer línea de texto.

    Esta es mi última línea de texto.

    ^Z
    1 archivo(s) copiado.

    De salida se parece a esto:

    C:\>tipo de out.txt

    Este es mi primer línea de texto.

    Esta es mi última línea de texto.

    (copiar con + out.txt, escriba su entrada, seguido de Ctrl-Z y el archivo es copiado)

    COPIAR CON significa «copia de la consola» (aceptar la entrada del usuario)

    • esto funciona desde la consola, pero ¿qué pasa desde el interior de un archivo de proceso por lotes?
  18. -5
    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
    

    **Va a agregar una línea en blanco al final, pero se puede resolver fácilmente, sólo por el uso de la copia con el método:

    C:\>copy con file.txt >nul
    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
    

    Tenga cuidado cuando usted escriba ^C y ^Z en cada caso.

    • Me puede faltar algo, pero yo no veo cómo esto responde a la pregunta. Si lo hace, por favor aclarar.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea