String manipulation - remove leading and trailing spaces

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Eureka!
Posts: 136
Joined: 25 Jul 2019 18:25

String manipulation - remove leading and trailing spaces

#1 Post by Eureka! » 05 Aug 2019 13:51

Just reading the String Manipulation page.

There is another way - beside the ones mentioned on that page - to remove leading and trailing spaces:

Code: Select all

set str=               15 Leading and Trailing  Spaces to truncate               &rem
echo."%str%"
for /f "tokens=*" %%A in ("%str%") do set str=%%~pnxA
set str=%str:~1%

echo."%str%"
OUTPUT:

Code: Select all

"               15 Leading and Trailing  Spaces to truncate               "
"15 Leading and Trailing  Spaces to truncate"
The %~pnxA will cause the string to be seen as a filename, without checking if it is an existing one.
Reporting path filename and extension will cause a leading "\" (from the path) that has to be stripped before getting the "unspaced" string.

HTH.

(obviously you should't use this method when the string contains a filename ..)

Sponge Belly
Posts: 216
Joined: 01 Oct 2012 13:32
Location: Ireland
Contact:

Re: String manipulation - remove leading and trailing spaces

#2 Post by Sponge Belly » 07 Aug 2019 15:27

Hi Eureka!

Welcome to the forum! :)

Dave Benham explored this approach in the novel method to right-trim spaces topic back in January, 2012. :shock:

As pointed out at the time, the method had too many shortcomings to ever be a general-purpose solution, and development ceased.

But trimming leading and trailing whitespace from a string was an obsession of mine. After many failed attempts, I eventually came up with the following code (see comments for credits):

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=" & for /f "skip=1" %%C in (
    'echo(^|replace ? . /w /u'
) do if not defined cr 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
Impenetrable spaghetti even Ed Dyreen would disown! Yes, it works. But look at the hoops you have to jump through first. Completely impractical. I’ve come to realise that just because something can be done in Batch, it doesn’t necessarily mean it should be. :(

Laters!

- SB

Eureka!
Posts: 136
Joined: 25 Jul 2019 18:25

Re: String manipulation - remove leading and trailing spaces

#3 Post by Eureka! » 11 Aug 2019 08:24

Sponge Belly wrote:
07 Aug 2019 15:27
Welcome to the forum! :)
Thanks!
... a general-purpose solution ...
I never had the illusion that this was a universal solution. Most times you know what format/layout the output will be. And if suitable, this is a short, straightforward fix.
(But hadn't thought about %'s and /'s)
Sponge Belly wrote:
07 Aug 2019 15:27
Impenetrable spaghetti even Ed Dyreen would disown!
Well, I could follow the flow. (not that I think that I'm able to reproduce it ...)
A lot of 'protection layers' to send strings through secondary shells (for command; pipes)
Not that I would encourage you to extend this even further, but it looks like it doesn't handle strings with % in them (not tested, though)

Thanks for your feedback. Appreciated!

BTW: I really liked your %= ... =% approach. I think I am going to use that too.

Post Reply