I have a homework task which needed to be done using just batch script. I need to rewrite all the numbers in .txt
file if they have dividing symbols .
or ,
but those strings may contain both words and numbers. Also the result should stay in the same file.
For example:
Lorem ipsum dolor 12.3254
2556,4646 ex commodo
would become
Lorem ipsum dolor 123254
25564646 ex commodo
I started with some code that looks like this:
@echo off
setlocal EnableDelayedExpansion
SET verfile=%1
FOR /f "tokens=* delims= " %%A IN (%verfile%) DO (
SET "Var=%%A"
FOR /l %%i IN (0, 1, 9) DO (
echo !Var! | findstr "."
IF %ERRORLEVEL% EQU 0 (
)
)
And now I have no idea how to continue it.
Can you help me please?
CodePudding user response:
@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.
CodePudding user response:
@echo off
setlocal enabledelayedexpansion
set "verfile=%~1"
echo before:
type "%verfile%"
for /f "usebackq tokens=*" %%a in ("%verfile%") do (
set strline=%%a
set strline=!strline:.=!
set strline=!strline:,=!
echo !strline!>>"%verfile%.tmp"
)
echo.
echo after:
type "%verfile%.tmp"
del /f /q "%verfile%.tmp"