Remove trailing spaces on a String

Microsoft Windows
Post Reply
User avatar
MigrationUser
Posts: 336
Joined: 2021-Jul-12, 1:37 pm
Contact:

Remove trailing spaces on a String

Post by MigrationUser »

25 Sep 2008 20:15
JLee

First, Great site - used it many times !

I know this is a trivial task to do and probably several ways to accomplish. Below is my first try using shell commands to drop out the trailing spaces on a string. In my particular case, there were trailing spaces on a directory name that was fetched from a OSQL / SQL2000 output file. The routine takes into consideration that there would be no spaces in the pathname than a single space.

(Disregard the ] , [ symbols as they were used to indicate the length of the trailing spaces)

Set _str1=[S:\Microsoft SQL Server\Backup ]

(two spaces between the colon & equal sign; in addition adding a special delimiter character "`" (reverse quote) to be used to help remove a single space if present after the initial trim. (this would happen if there are a odd number of trailing spaces).

Set _FixStr1=%_str1: =%`

(replace the possible remaining (blank & reverse quote) if present; no harm if not)

Set _FixStr2=%_FixStr1: `=%

(replace the possible remaining (reverse quote) if present; no harm if not)

Set _FixStr1=%_FixStr2:`=%


Ok. _FixStr1 should now contain the pathname without trailing spaces. If anyone else has suggestions for a better approach, they would be appreciated. thanks.

Joey

Last edited by JLee (25 Sep 2008 22:58)

----------------------------

#2 27 Sep 2008 10:40
bluesxman

Here's how I'd do it. It might seem a little over complicated, but this method makes no assumptions about the input string (I.E. repeated spaces within the string we want to keep won't be a problem) and you could strip just about any character from the end of the input variable.

Code: Select all

@echo off

REM " used below to show the trailing spaces (but are also perfectly legal to use in the following command)
set "_str1=S:\Microsoft SQL Server\Backup                                                      "

echo:IN : "%_str1%"

REM call the sub-routine, telling it the name of the variable we want to work with
REM and also which (single) character we want to strip from the end of the string
call :RemoveTrailingChar "_str1" " "

echo:OUT: "%_str1%"

pause

goto :EOF

:RemoveTrailingChar

    REM store the name of the incoming variable
    set "inVar=%~1"
    
    REM store the character to strip from the end (script assumes this is 1 character long)
    set "stripChar=%~2"

    if not defined stripChar goto :EOF & REM in case we did something stupid, like not supplying a character to strip
    
    REM put the value of the input variable into a working variable
    call set "workVar=%%%inVar%%%"

    :loop

        REM this next line is only here so you can see what's happing
        echo:     "%workVar%"

        if "%workVar:~-1%" NEQ "%stripChar%" (
        REM if the last character of workVar doesn't equal the stripChar, we're done here
            set "%inVar%=%workVar%"
        ) ELSE (
        REM otherwise remove the last character of workVar and loop
            set "workVar=%workVar:~0,-1%"
            REM much as I hate to use goto, using the call command has a performance overhead
            REM when used repeatedly -- which is only really a problem for VERY long input
            goto :loop
        )
goto :EOF
Last edited by bluesxman (27 Sep 2008 15:38)

----------------------------

#3 29 Sep 2008 00:54
JLee

Yes, this method will account for any trailing character(s) and also with respect to spaces. As you pointed out that long strings would cause more CPU cycles executing to drop the characters one at a time where a single command statement would remove the majority of the characters; however, it comes down to a trade off of high performance and possibility of incorrect results versus lower performance but with consistent correct results. Anyway, good approach and another benefit of this site is where code methods ideas are presented to achieve a specific solution but also provide someone a technique that could be used in separate type of application.

Last edited by JLee (29 Sep 2008 00:55)

----------------------------

#4 01 Jan 2018 21:53
Sponge Belly

HNY Everyone! :)

The :trimAll subroutine below trims leading and trailing spaces and tabs from a string. It can be safely CALLed with delayed expansion disabled or enabled. It handles poison characters (eg, !, %, ^, &, >, etc). CRs and LFs are not supported.

The subroutine uses call-by-reference and accepts 2 arguments: the name of the variable to store the trimmed string; and the name of the variable of the untrimmed original. Read comments for references and more info.

Code: Select all

@echo off & setLocal enableExtensions disableDelayedExpansion
:: https://www.dostips.com/forum/viewtopic.php?t=4308
(call;) %= sets errorLevel to 0 =%
(set lf=^
%= BLANK LINE REQUIRED =%
)
:: kudos to Carlos for superior method of capturing CR
:: https://www.dostips.com/forum/viewtopic.php?p=40757#p40757
set "cr=" & if not defined cr for /f "skip=1" %%C in (
    'echo(^|replace ? . /w /u'
) do set "cr=%%C"

set ^"orig=  !random!  !  ^^!  ^^^^!  ^"^^  ^&^"^&  ^^^" %%os%%  ^"

call :trimAll res1 orig
setLocal enableDelayedExpansion
call :trimAll res2 orig
echo(orig: [!orig!]
echo(res1: [!res1!]
echo(res2: [!res2!]
endLocal

endLocal & goto :EOF

:trimAll result= original=
:: trims leading and trailing whitespace from a string
:: special thanks to Jeb for
:: https://stackoverflow.com/a/8257951
setLocal
set "ddx=!" %= is delayed expansion enabled or disabled? =%
setLocal enableDelayedExpansion
set "die=" & if not defined %2 (
    >&2 echo(  ERROR: var "%2" not defined & set "die=1"
) else set "str=!%2!" %= if =%

if not defined die for %%L in ("!lf!") ^
do if "!str!" neq "!str:%%~L=!" (
    >&2 echo(  ERROR: var "%2" contains linefeeds & set "die=1"
) %= if =%

if not defined die for %%C in ("!cr!") ^
do if "!str!" neq "!str:%%~C=!" (
    >&2 echo(  ERROR: var "%2" contains carriage returns
    set "die=1"
) %= if =%

if defined die goto die

(for /f eol^= %%A in ("!str!") do rem nop
) || (
    >&2 echo(WARNING: var "%2" consists entirely of whitespace
    endLocal & endLocal & set "%1=" & exit /b 0
) %= cond exec =%

:: prepare string for trimming...
:: double carets
set "str=!str:^=^^^^!"
:: double quotes
set "str=!str:"=""!"
:: escape exclaims
set "str=%str:!=^^^!%" !

:: act of CALLing subfunction with
:: expanded string trims trailing whitespace
call :_trimAll "%%str%%

:: prepare string to be passed over endLocal boundary...
:: double carets again if delayed expansion enabled
if not defined ddx set "str=!str:^=^^^^!"
:: escape exclaims again if delayed expansion enabled
if not defined ddx set "str=%str:!=^^^!%" !
:: restore quotes
set "str=!str:""="!"

:: pass string over endLocal boundary and trim leading whitespace
for /f tokens^=*^ eol^= %%a in ("!str!") do (
    endLocal & endLocal & set "%1=%%a" !
) %= for /f =%
exit /b 0

:die
endLocal & endLocal & set "%1=" & exit /b 1

:_trimAll
:: subfunction
:: trailing exclaim is required as explained by Jeb at
:: https://www.dostips.com/forum/viewtopic.php?p=6933#p6933
set "str=%~1" !
exit /b 0
Enjoy! :D

- SB
Post Reply