Reputation: 45
how can i split the string
" This is a text with spaces "
that is in the variable "string" into text parts without loosing the spaces ?
set string="# This is a text with spaces #"
should be split into
"# This"
" is"
" a"
" text"
" with"
" spaces #"
Using For /F "delims= " ...
doesn't work because it eliminates all spaces.
Is there a 'simple' solution or can anyone explain how to parse the string character by character so i can count up spaces to first character, then read all characters until next space and write the counted spaces and the read characters together to a new/temp variable ??
thanks
Upvotes: 2
Views: 396
Reputation: 24466
Yeah, I don't really understand the #
either. What is it about " spaces #" that makes it hold onto the trailing spaces, while all other elements keep the preceding but not the proceeding spaces?
Oh, well, effort spent in asking = effort spent in answering. Do with this what you will.
@if (@a==@b) @end /*
:: batch portion
@echo off
setlocal
call :split "# This is a text with spaces #"
exit /b
:split <string>
cscript /nologo /e:jscript "%~f0" "%~1"
goto :EOF
:: JScript portion */
WSH.Echo(WSH.Arguments(0).match(/\s*\S+/g).join('\n'));
Output:
#
This
is
a
text
with
spaces
#
If you want the first + second, and the penultimate + ultimate elements joined, modify the JScript portion of the above script as follows:
:: JScript portion */
var m = WSH.Arguments(0).match(/\s*\S+/g);
m[0] = m.shift() + m[0];
m[m.length - 2] += m.pop();
WSH.Echo(m.join('\n'));
Output:
# This
is
a
text
with
spaces #
And if you want each element enclosed in quotation marks, change the last line as follows:
WSH.Echo('"' + m.join('"\n"') + '"');
Output:
"# This"
" is"
" a"
" text"
" with"
" spaces #"
Upvotes: 3
Reputation: 130819
If I had to accomplish this obscure task, I would use a hybrid JScript/batch technique like in rojo's answer. However, I would use a REPL.BAT utility that I have already written. Assuming my REPL.BAT is in either the current folder, or else somewhere in the PATH, then the following will work:
@echo off
setlocal enableDelayedExpansion
set "string=# This is a text with spaces #"
:: Build an "array" of text parts
set cnt=0
for /f delims^=^ eol^= %%A in ('repl "([^ ])(?= )" "$1\n" xs string') do (
set /a cnt+=1
set "string!cnt!=%%A"
)
:: Print the array values
for /l %%N in (1 1 %cnt%) do echo string%%N=[!string%%N!]
But if I wanted a pure batch solution, I would use the fairly efficient method below:
@echo off
setlocal enableDelayedExpansion
set "string=# This is a text with spaces #"
:: Define LF to contain a single line feed character (0x0A)
set LF=^
:: Above 2 blank lines are critical - DO NOT REMOVE
:: Insert a line feed before every space
for %%n in ("!LF!") do set "string=!string: =%%~n !"
:loop Remove line feeds sandwiched by spaces
for %%n in ("!LF!") do set "string2=!string: %%~n = !"
if "!string2!" neq "!string!" (
set "string=!string2!"
goto :loop
)
:: Build an "array" of text parts: FOR /F splits the string at line feeds
set /a cnt=0
for /f delims^=^ eol^= %%A in ("!string!") do (
set /a cnt+=1
set "string!cnt!=%%A"
)
:: Print out the array values
for /l %%N in (1 1 %cnt%) do echo string%%N=[!string%%N!]
Both solutions above give the following output:
string1=[#]
string2=[ This]
string3=[ is]
string4=[ a]
string5=[ text]
string6=[ with]
string7=[ spaces]
string8=[ #]
Note that the FOR loop %%A
expansion will corrupt the results if the string contains !
due to delayed expansion. This limitation can be eliminated with additional coding. All the other posted solutions that use a FOR loop suffer from this same limitation. (at least they did when I wrote this)
Upvotes: 2
Reputation: 37569
Try this:
@echo off &setlocal enabledelayedexpansion
set "string=# This is a text with spaces #"
set string1=%string%
for %%i in (%string%) do (
set string1=!string1: %%i = "%%i" !
set /a strings+=1
)
set string1=#"%string1:~1,-1%"#
set string1=%string1:"= "%
for %%i in (%string1%) do (
set /a count+=1
set string2=%%i
set string2=!string2: "=!
set string2=!string2:"=!
if !count! equ 2 (
set $s1=!$s1!!string2!
)else if !count! equ %strings% (
set /a count-=1
call set $s!count!=%%$s!count!%%!string2!
) else set $s!count!=!string2!
)
for /f "tokens=1*delims==" %%i in ('set "$s"') do echo "%%j"
Output:
"# This"
" is"
" a"
" text"
" with"
" spaces #"
Upvotes: 2
Reputation: 29339
the trick is substituting the contiguous spaces by just one space and the rest by some arbitrary character. Assuming your string does not contain #
s and that there are no more than 9 contiguous spaces, you can try this
set st=%st: = ########%
set st=%st: = #######%
set st=%st: = ######%
set st=%st: = #####%
set st=%st: = ####%
set st=%st: = ###%
set st=%st: = ##%
set st=%st: = #%
then you may parse with for /f
and substitute back your #
s by spaces
setlocal enabledelayedexpansion
for /f %%a in ("%st%") do (
set ss= %%a
echo !ss:#= !
)
note that set
inside the parentheses block requires you to enable delayed expansion and to use the !
syntax (see HELP SET
)
But this technique will only extract the first substring. To generalize, you need another trick, that is substituting the spaces into newlines so that the for /f
will loop kinda line by line
note that in order to obtain a newline char you need to preserve the two blank lines after the set
command
set nl=^
rem continue two lines down....
for /f %%a in ("%st: =!nl!%") do (
set ss= %%a
set ss=!ss:#= !
echo [!ss!]
)
Upvotes: 2
Reputation: 6657
I don't see a simple solution in batch, though of course if you can consider powershell or javascript you'll be working with a more appropriate toolset for string manipulation.
Sticking with the batch requirement, you can loop through character by character and "collect" your words with something like this:
@echo off
setlocal enabledelayedexpansion
set "string= This is a text with spaces "
set idx=0
set "word="
set "char="
set "lastchar= "
:loop
if "!string:~%idx%!" equ "" goto :eof
set char=!string:~%idx%,1!
if "%char%" equ " " (
if "%lastchar%" neq " " (
echo [%word%]
set word=%char%
) else (
set word=%word%%char%
)
) else (
set word=%word%%char%
)
set lastchar=%char%
set /a idx=%idx%+1
goto loop
This script uses batch's substring feature !string:~%idx%,1
to grab a single character from the string, incrementing idx
with each loop. Then it's just a matter of processing the word (echo
in this example) when the previous character was not a space and the current one is.
This writes out:
[ This]
[ is]
[ a]
[ text]
[ with]
[ spaces]
Note that I'm ignoring the #
you had in your example because I don't understand where they fit in.
Upvotes: 2