Remove trailing spaces from a file using Windows batch?

前端 未结 7 1291
借酒劲吻你
借酒劲吻你 2020-12-02 02:33

How could I trim all trailing spaces from a text file using the Windows command prompt?

7条回答
  •  南方客
    南方客 (楼主)
    2020-12-02 03:08

    I just found a very nice solution for trimming off white-spaces of a string:
    Have you ever called a sub-routine using call and expanded all arguments using %*? You will notice that any leading and/or trailing white-spaces are removed. Any white-spaces occurring in between other characters are preserved; so are all the other command token separators ,, ;, = and also the non-break space (character code 0xFF). This effect I am going to utilise for my script:

    @echo off
    
    set "STR="
    set /P STR="Enter string: "
    
    rem /* Enable Delayed Expansion to avoid trouble with
    rem    special characters: `&`, `<`, `>`, `|`, `^` */
    setlocal EnableDelayedExpansion
    echo You entered: `!STR!`
    call :TRIM !STR!
    echo And trimmed: `!RES!`
    endlocal
    
    exit /B
    
    :TRIM
    set "RES=%*"
    exit /B
    

    This script expects a string entered by the user which is then trimmed. This can of course also be applied on lines of a file (which the original question is about, but reading such line by line using for /F is shown in other answers anyway, so I skip this herein). To trim the string on one side only, add a single character to the opposite side prior to trimming and remove it afterwards.

    This approach has got some limitations though: it does not handle characters %, !, ^ and " properly. To overcome this, several intermediate string manipulation operations become required:

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    
    set "STR="
    set /P STR="Enter string: "
    
    setlocal EnableDelayedExpansion
    echo You entered: `!STR!`
    set "STR=!STR:%%=%%%%!"
    set "STR=!STR:"=""!^"
    if not "%STR%"=="%STR:!=%" set "STR=!STR:^=^^^^!"
    set "STR=%STR:!=^^^!%"
    call :TRIM !STR!
    set "RES=!RES:""="!^"
    echo And trimmed: `!RES!`
    endlocal
    
    endlocal
    exit /B
    
    :TRIM
    set "RES=%*"
    exit /B
    

    Update

    Both of the above scripts cannot handle the characters &, <, > and |, because call seems to become aborted as soon as such a character appears in an unquoted and unescaped manner.

    However, I finally found a way to fix that and come up with an approach that can successfully deal with all characters (except perhaps some control characters, which I did not test):

    @echo off
    setlocal EnableExtensions EnableDelayedExpansion
    
    rem // The last white-space in `STRING` is a tabulator:
    set "RESULT=" & set "STRING=   (<&>"^|)^^!^^^^;,=   ^"
    echo Input string: `!STRING!`
    
    rem // Double quotes to avoid troubles with unbalanced ones:
    if defined STRING set "STRING=!STRING:"=""!^"
    rem // Particularly handle carets and exclamation marks as delayed expansion is enabled:
    if defined STRING set "STRING=!STRING:^=^^^^!"
    if defined STRING set "STRING=%STRING:!=^^^!%" !
    if defined STRING (
        rem // Escape all characters that `call` has got troubles with:
        set "STRING=!STRING:^=^^!"
        set "STRING=!STRING:&=^&!"
        set "STRING=!STRING:<=^=^>!"
        set "STRING=!STRING:|=^|!"
    )
    rem /* Call the sub-routine here; the strigs `!=!` constitute undefined dummy variables
    rem    with an illegal name, which eventually become removed; the purpose of them us to
    rem    enable usage of that `call` inside of a `for` loop with the meta-variable `%%S`,
    rem    which would otherwise become unintentionally expanded rather than `%%STRING%%`,
    rem    which literally contained `%%S`; the `!=!` at the end is just there in case you
    rem    want to append another string that could also match another `for` meta-variable;
    rem    note that `!!` is not possible as this would be collapsed to a single `!`, so
    rem    a (most probably undefined) variable `!STRING%!` would then become expanded: */
    call :TRIM %%!=!STRING%%!=!
    rem /* The caret doubling done by `call` does not need to be reverted, because due to
    rem    doubling of the quotes carets appear unquoted, so implicit reversion occurs here;
    rem    of course the doubling of the quotes must eventually be undone: */
    if defined RESULT set "RESULT=!RESULT:""="!^"
    echo Now trimmed: `!RESULT!`
    
    endlocal
    exit /B
    
    :TRIM
        rem // This is the effective line that does the left- and right-trimming:
        set "RESULT=%*" !
        exit /B
    

提交回复
热议问题