Reputation: 35
In batch I'm trying to split a string into substrings preferably based on a delimiter.
This example works but is there a better way to do this:
for /f "tokens=1-20 delims=:" %%a in (string.txt) do (
echo %%a& echo.%%b& echo.%%c& echo.%%d& echo.%%e& echo.%%f& echo.%%g& echo.%%h& echo.%%i& echo.%%j
echo.%%k& echo.%%l& echo.%%m& echo.%%n& echo.%%o& echo.%%p& echo.%%q& echo.%%r& echo.%%s& echo.%%t
) >substrings.txt
I have tried this code from Magoo which works for default delimiters but fails using colon:
@echo off
setLocal
for /f "delims=:" %%a in (string.txt) do (
for %%i in (%%a) do echo %%i >>substrings.txt
)
I have also tried this code from Aacini but it seems to fail using special characters.
@echo off
setlocal EnableDelayedExpansion
set i=1
set "x=%string%"
set "x!i!=%x::=" & set /A i+=1 & set "x!i!=%"
set x >substrings.txt
An example %string% var or string.txt is:
Select project:/option:report name="Sustainability":option value="201":Huonville:/option:/report:report name="Energy and Water Management":option value="102":Cygnet:/option:/report:report name="Tree Management":option value="101":Cygnet:/option:/report:option disabled="disabled":/option:/select
I am trying to output %string% var or string.txt to substring.txt as follows:
Select project
/option
report name="Sustainability"
option value="201"
Huonville
/option
/report
report name="Energy and Water Management"
option value="102"
Cygnet
/option
/report
report name="Tree Management"
option value="101"
Cygnet
/option
/report
option disabled="disabled"
/option
/select
Any help would be greatly appreciated. Thanks
Upvotes: 1
Views: 1001
Reputation: 841
See @dbenham's AMAZING CERTUTIL
string replacement technique. It works for any characters, even exclams!
@echo off
====SETLOCAL EnableDelayedExpansion EnableExtensions
set "B=^!"
set "C=^"
set ^"L=^
%===Line Feed===%
"
for /F "eol=N" %%C in ('wmic os get Name /value') do set "R=%%C" Carriage Return
set ^"E=!R!!L!" CRLF
>nul 2>&1 certutil -f -encodehex String.txt "%temp%\hex.txt" 4
pushd "%temp%"
>expand.txt (FOR /F "delims=" %%A in (hex.txt) do FOR %%B in (%%A) do (
set "char=%%B"
REM ! --> !B! ###
set "char=!char:21=21 42 21!"
REM ^ --> !C! ###
set "char=!char:5e=21 43 21!"
REM <CR> --> !R! ###
set "char=!char:0a=21 4c 21!"
REM <LF> --> !L! ###
set "char=!char:0d=21 52 21!"
REM : --> !R!!L! ###
set "char=!char:3a=21 45 21!"
echo(!char!
))
>nul 2>&1 certutil -f -decodehex expand.txt rawContent.txt
for /f delims^=^ eol^= %%A in (rawContent.txt) do set "modified=%%A"
del hex.txt expand.txt rawContent.txt
popd
>substring.txt (
echo(!modified!
)
Upvotes: 1
Reputation: 35
This is a summary of what Stephan came up with.
@echo off
setlocal enabledelayedexpansion
set /p string=<"input.txt"
set "string=%string: =@%"
set "string="%string::=" "%"
(for %%a in (%string%) do (
set "output=%%~a"
echo !output:@= !
))>output.txt
Set string or input text file (modify line 3).
set /p string=<"input.txt"
The delimiter in this example is colon [:] which follows after [string:] (modify line 5).
set "string="%string::=" "%"
If string or input.txt contains quotes %string% may need to be double quoted (modify line 3).
for /f "delims=" %%a in (input.txt) do (set string="%%a")
@echo off
setlocal enabledelayedexpansion
for /f "delims=" %%a in (input.txt) do (set string="%%a")
set "string=%string: =@%"
set "string="%string::=" "%"
(for %%a in (%string%) do (
set "output=%%~a"
echo !output:@= !
))>output.txt
Upvotes: 0
Reputation: 56180
When you use for /f
, you need to know how many tokens there are (and there is a limit for max tokens).
You need a plain for
loop, but you can't choose, which delimiter should be used.
So replace every delimiter with a space. Be sure to have quotes around each "token" to take care of original spaces. To do this, put quotes around the whole string and replace the delimter :
with " "
:
@echo off
setlocal enabledelayedexpansion
set "string=Select project:/option:report name="Sustainability":option value="201":Huonville:/option:/report:report name="Energy and Water Management":option value="102":Cygnet:/option:/report:report name="Tree Management":option value="101":Cygnet:/option:/report:option disabled="disabled":/option:/select""
set "string=%string: =@%"
set "string="%string::=" "%"
(for %%a in (%string%) do (
set "out=%%~a"
echo !out:@= !
))>out.txt
echo take a look at the modified string:
echo %string%
echo/
type out.txt
Another approach (just for academic reasons):
@echo off
setlocal
set "string=Select project:/option:report name="Sustainability":option value="201":Huonville:/option:/report:report name="Energy and Water Management":option value="102":Cygnet:/option:/report:report name="Tree Management":option value="101":Cygnet:/option:/report:option disabled="disabled":/option:/select"
call :recur %string%
goto :eof
:recur
rem echo loop with %*
for /f "tokens=1,* delims=:" %%a in ("%*") do (
echo %%a
if not "%%~b" == "" call :recur %%b
goto :eof
)
echo.
Note: there is a recursion limit (due to stack-size). It works with the given string, but may fail when the string contains more "tokens".
Upvotes: 4