@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
rem The following settings for the source directory and filename are names
rem that I use for testing and deliberately include names which include spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
SET "filename1=%sourcedir%\q73553463.txt"
:: remove variables starting #
FOR /F "delims==" %%b In ('set # 2^>Nul') DO SET "%%b="
SET /a linecount=0
:: Read entire file into memory
FOR /f "usebackqdelims=" %%e IN ("%filename1%") DO (
rem next line number
SET /a linecount +=1
rem record in memory
SET "#!linecount!=%%e"
)
:: process each line removing [,.] following a digit
:: and report to original file
(
FOR /L %%e IN (1,1,%linecount%) DO (
FOR %%c IN ("." ",") DO FOR /L %%y IN (0,1,9) DO SET "#%%e=!#%%e:%%y%%~c=%%y!"
ECHO !#%%e!
)
)>"%filename1%"
TYPE "%filename1%"
GOTO :EOF
The set #
command will generate a list like
#whatever=something
#whateverelse=somethingelse
for all variables that are currently set and start #
.BUT it would be unusual to have any variable set that starts #
so set
would generate an error. The 2^>nul
sends any error-report (on standard device stderr, which is device 2
) to nul
that is, nowhere. The caret ^
is required because cmd
needs to distinguish between a part of the set
command and a part of the for
.
The for/f...%%b using delims
of =
generates "tokens" from the list generated by the set
. Tokens are separated by any sequence of any of the delimiters specified between =
and "
, and by default, "token1" is selected, so the strings applied to %%b
are
#whatever
#whateverelse
and these variables need to be set to nothing.
See for /?
from the prompt for documentation on for
or browse thousands of examples on SO.
Use set "var=value"
for setting string values - this avoids problems caused by trailing spaces which can cause chaos. Once bitten, twice shy.
Then we read the file. Using "delims="
sets no delimiters, hence the whole line forms "token 1" which is assigned to %%e
. The usebackq
changes the meaning of "
so that a double-quoted filename may be used. The filename I've used includes a Space but if there are no separator characters in the name, the quotes and usebackq
can be omitted (again, ref for/?
)
Then add 1 to the linecount and record the line in memory by assigning it to #!linecount!
. The !linecount!
is required because linecount
is varying within the block
(parenthesised sequence of lines) - and with delayedexpansion
enabled, %linecount%
yields the value when the block was encountered, and !linecount!
the run-time or instantaneous value - as it changes within the block.
Stephan's DELAYEDEXPANSION link
So - having established #1
, #2
..#%linecount%
with the lines from the file, we can process those variables and produce a replacement file.
Note that there is a block formed by ( for...%%e...)>filename
. This allows any echo
ed data within the block to be redirected to the file. >
redirects to a new version whereas >>
would append to any existing file.
So - we iterate through all of the #linenumber
lines using a for /L
on %%e
. For each of these, we set %%c
to "."
and %%y
to 0
to 9
and then replace any string %%y%%c
with %%y
(3.
gets replaced by 3
for example). Then repeat with %%c
set to ","
. set /?
provides documentation and browsing SO examples.
But Woah, Neddie! There's a little trick here. ,
is a list-separator so (. ,)
won't work - it will be treated as (.)
. Using the quotes allows cmd
to read each character separately, and we need to use %%~c
instead of %%c
to dump the quotes.
So - take a look around. You can do a lot with batch if you're devious enough. And no doubt you'll be challenged if you present this solution. Be ready to explain it. A really good way to follow what's happening is to turn echo
on and watch the magic step-by-step. Use pause
liberally and perhaps remove the >"%filename1%"
to prevent the report going to the file while you're observing what's happening.