How to split double quoted line into multiple lines in Windows batch file?

后端 未结 5 1638

Long commands in Windows batch files can be split to multiple lines by using the ^ as mentioned in Long commands split over multiple lines in Windows Vista batc

相关标签:
5条回答
  • 2020-11-30 04:23

    The clear advantage of @solvingJ's method over the variants of Jeb is that it is quite obvious what happens and that there is a spatial seperation of on the left hand the ugly cmd stuff and on the right the actual content. And it can be improved in readability by putting more spaces between the left and the right part:

    set      CMD=   docker run --rm
    set CMD=%CMD%     --platform=linux
    set CMD=%CMD%     -v %CD%:/work
    set CMD=%CMD%     dockcross/%IMAGE_NAME%
    set CMD=%CMD%     /bin/sh -c
    set CMD=%CMD%       "mkdir build-%IMAGE_NAME% &&
    set CMD=%CMD%       cd build-%IMAGE_NAME% &&
    set CMD=%CMD%       cmake .. &&
    set CMD=%CMD%       cmake --build ."
    

    Unfortunately it is not possible to demonstrate this in a comment because multiple spaces are reduced to one there. So I do in an answer what is actually just a comment to @solvingJ's answer, which I consider the best.

    0 讨论(0)
  • 2020-11-30 04:24

    The most straight forward answer is to escape the quotes. They will be printed, but they will not functionally quote the contents as far as CMD.EXE is concerned.

    @echo off
    echo ^"A very long line I want to ^
    split into two lines^"
    

    Any special characters that appear in the line must also be escaped since they are no longer functionally quoted.

    @echo off
    echo ^"A very long line I want to ^
    split into two lines ^
    that also contains special characters ^^ ^& ^| ^> ^< ^"
    

    As jeb said, the line continuation escapes the first character of the next line. So if the first character of the next line happens to be a special character, it should not be escaped a second time. The code below will give the exact same results as the previous example.

    @echo off
    echo ^"A very long line I want to ^
    split into two lines ^
    that also contains special characters ^^ ^
    & ^| ^> ^< ^"
    
    0 讨论(0)
  • 2020-11-30 04:36

    I came up with my own method for this today, and I've never seen it suggested anywhere so I thought I'd post it here. Certainly, it's not elegant in an objective sense. I would say it has it's own unique kind of ugly and some limitations, but I find it far more "ergonomic" when compared to the alternatives.

    Specifically, this method has the unique characteristic of not needing to escape anything, while still performing typical variable substitution. This enables me to to take some string that looks exactly how I want it, spread it across multiple lines, and add a prefix to each line without changing anything else in the string. Thus, there's no trial-and-error needed to figure out how special characters and escape characters might interact. Overall, I think it reduces the cognitive load needed to deterministically produce a complicated string variable over multiple lines, which is good for me because I don't want to have to think hard and get frustrated with incidental complexity like the nuances of the windows command interpreter. Also, a similar technique can be used on linux bash, making it somewhat portable.

    Note: I've not thoroughly tested it, it might not work for some use cases, I don't know. However, the example has a fair number of seemingly troublesome characters an it works, so it seems somewhat robust.

    set IMAGE_NAME=android-arm64
    set CMD=docker run --rm
    set CMD=%CMD% --platform=linux
    set CMD=%CMD% -v %CD%:/work
    set CMD=%CMD% dockcross/%IMAGE_NAME%
    set CMD=%CMD% /bin/sh -c
    set CMD=%CMD% "mkdir build-%IMAGE_NAME% &&
    set CMD=%CMD% cd build-%IMAGE_NAME% &&
    set CMD=%CMD% cmake .. &&
    set CMD=%CMD% cmake --build ."
    
    echo %CMD%
    

    In my case, it's a command, so I can run it with:

    %CMD%
    

    I'd be open to any feedback or suggestions about this method. Perhaps it can even be improved.

    0 讨论(0)
  • 2020-11-30 04:41

    I see three possible workarounds.

    1) Building the line combining multiple for-parameters.

    @echo off
    SETLOCAL EnableDelayedExpansion
    
    set "line="
    for %%a in ("line1" 
    "line2"
    "line3"
    "line4"
    ) do set line=!line!%%~a
    echo !line!
    

    Drawback: It drops lines, when there is a ? or * in the text.

    2) Leaving the "quote" at the end of each line

    @echo on
    SETLOCAL EnableDelayedExpansion
    
    set "line=line1 & x#"^
     "line2 & a#"^
     "line3 & b #"^
     "line4 & c "
    
    set "line=!line:#" "=!"
    echo !line!
    

    The first space in each line is important, because the caret works as multiline character but it also escapes the first character, so also a quote would be escaped.
    So I replace the unnessary #" " after building the line.

    EDIT Added: 3) Disappearing quotes

    setlocal EnableDelayedExpansion
    echo "A very long line I want to !="!^
    split into two lines"
    

    In my opinion this is the best way, it works as the parser first see the quotes and therefore the last caret will work, as it seems to be outside of the quotes.
    But this !="! expression will expand the variable named =", but such a variable name can't exists (an equal sign can't occur as first character) so it expands to nothing.

    You can also create safe expressions, they will always escape out of quotes, independent if there is a quote or not in the line.
    !="^"!

    echo This multiline works !="^"!^
    as expected
    echo "This multiline works !="^"!^
    too"
    

    If you want avoid delayed expansion, you could also use a -FOR-Loop like

    for %%^" in ("") do (
    echo "This multiline works %%~"^
    too"
    )
    
    0 讨论(0)
  • 2020-11-30 04:49

    If you want to add blank lines then ensure you have a space BEFORE the ^ on the 2nd line

    echo Hello world^ ^ Have a good day !

    0 讨论(0)
提交回复
热议问题