How do you strip quotes out of an ECHO'ed string in a Windows batch file?

后端 未结 12 1871
萌比男神i
萌比男神i 2020-12-05 04:23

I have a Windows batch file I\'m creating, but I have to ECHO a large complex string, so I\'m having to put double quotes on either end. The problem is that the quotes are

12条回答
  •  粉色の甜心
    2020-12-05 05:09

    To remove all quotation marks from a set variable, you need Delayed Variable Expansion to securely expand the variable and process it. Expansion using percent signs (i.e. %VAR% and %1) are inherently unsafe (they are vulnerable to command injection; read this for details).

    SETLOCAL EnableDelayedExpansion
    SET VAR=A ^"quoted^" text.
    REM This strips all quotes from VAR:
    ECHO !VAR:^"=!
    REM Really that's it.
    

    To strip quotes from a text file or a command output, things will get complicated because with Delayed Expansion, string like !VAR! within the text document will get expanded (within the %%i expansion in FOR /F) when it shouldn't. (This is another vulnerability—information disclosure—that's not documented elsewhere.)

    To safely parse the document, a switch between delayed-expansion-enabled and -disabled environment is needed.

    REM Suppose we fetch the text from text.txt
    
    SETLOCAL DisableDelayedExpansion
    REM The FOR options here employs a trick to disable both "delims"
    REM characters (i.e. field separators) and "eol" character (i.e. comment
    REM character).
    FOR /F delims^=^ eol^= %%L IN (text.txt) DO (
    
        REM This expansion is safe because cmd.exe expands %%L after quotes
        REM parsing as long as DelayedExpansion is Disabled. Even when %%L
        REM can contain quotes, carets and exclamation marks.
        SET "line=%%L"
    
        CALL :strip_quotes
        REM Print out the result. (We can't use !line! here without delayed
        REM expansion, so do so in a subroutine.)
        CALL :print_line
    )
    ENDLOCAL
    GOTO :EOF
    
    REM Reads !line! variable and strips quotes from it.
    :strip_quotes
        SETLOCAL EnableDelayedExpansion
        SET line=!line:^"=!
    
        REM Make the variable out of SETLOCAL
        REM I'm expecting you know how this works:
        REM (You may use ampersand instead:
        REM `ENDLOCAL & SET "line=%line%"`
        REM I just present another way that works.)
        (
        ENDLOCAL
        SET "line=%line%"
        )
    GOTO :EOF
    
    :print_line
        SETLOCAL EnableDelayedExpansion
        ECHO !line!
        ENDLOCAL
    GOTO :EOF
    

    The delims^=^ eol^= in the code above probably needs explanation: This effectively disables both "delims" characters (i.e. field separators) and "eol" character (i.e. comment character). Without it, the "delims" will default to tab and space and "eol" defaults to a semicolon.

    • The eol= token always read whichever the next character it is after the equal sign. To disable it this token has to be in the end of the options string so that no character may be used for "eol", effectively disabling it. If the options string is quoted, it might use quotation mark (") as the "eol", so we must not quote the options string.
    • The delims= option, when it's not the last option in the options string, will be terminated by a space. (To include space in "delims" it has to be the last option of FOR /F options.) So delims= followed by a space and then another option disables the "delims".

提交回复
热议问题