Good evening everyone,
I do not know anything about a batch file but I need it to do something.
Let me explain: what I want to do is to open a file.c and browse for this line of code
#define var ((uint32_t) 1000)
what I want after is to change the value 1000 by a value enter previously by the user, except that this value will not always be 1000, precisely every time the user enter a value for example 250000,
I want it to be replaced in my .c file and then I need to replace 250000 of
#define var ((uint32_t) 250000)
by another variable again and again, so I would like my program to replace what has after define var ((uint32_t) and replace with what the user has entered I hope you have a little understanding of what I want to do.
I add my program, but it does not do really work, do you have any ideas pleaaaase?
@echo off
setLocal EnableDelayedExpansion
SET "file=(C:\Users\astre\Desktop\test\fichier.c)"
SET /p NouvelVal= Entrez la fréquence que vous souhaitez entre 4Mhz et 24 MHz:
SET WordToSearch=#define HSE_VALUE((uint32_t)25000000)
SET Replacement=#define HSE_VALUE((uint32_t)%NouvelVal%)
for /f "tokens=* delims= " %%a in %file% do (
set str=%%a
set str=!str:%WordToSearch%=%Replacement%!
echo !str!>>test2.txt
)
type test2.txt>fichier.c
del test2.txt
pause
Modifying text files by batch scripts is not that trivial, particularly when it is a format that can easily be damaged when even only a single character becomes added/changed/removed, like (C) source code.
Nevertheless I had to try to manage it with pure batch scripting -- see the explanatory remarks in the code.
The main challenges are:
#define var ((uint32_t) 1000), which may contain multiple white-spaces (SPACEs and TABs) at almost any position, except in the keywords and the number, of course;uint32_t relative to the number;So here it is:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_FILE=C:\Users\astre\Desktop\test\fichier.c" & rem // (path or name of input file)
set "_TEMP=%TEMP%\%~n0_%RANDOM%.tmp" & rem // (path or name of temporary file)
rem // Gather TAB character:
for /F "delims=" %%T in ('forfiles /P "%~dp0." /M "%~nx0" /C "cmd /C echo/0x09"') do set "_T=%%T"
rem // Build white-space classes for search expressions:
set "_S=[ %_T%]" & set "_S0=[ %_T%]*" & set "_S1=[ %_T%][ %_T%]*"
rem // Build digit classes for search expressions:
set "_D=[0123456789]" & set "_D0=[0123456789]*" & set "_D1=[0123456789][0123456789]*"
rem // Define expression (word) before number to replace:
set "_SPLIT=uint32_t"
rem // Build search expression for `findstr`:
set "_SEARCH=^%_S0%#define%_S1%var%_S1%(%_S0%(%_S0%%_SPLIT%%_S0%)%_S1%%_D1%%_S0%)%_S0%$"
rem // Write output to temporary file:
> "%_TEMP%" (
set "FLAG="
rem /* Read input file line by line, prefixed by current line number,
rem so lines appear non-empty to `for /F`, which would be ignored: */
for /F "delims=" %%L in ('findstr /N "^" "%_FILE%"') do (
set "LINE=%%L"
setlocal EnableDelayedExpansion
set "LINE=!LINE:*:=!"
rem // Check whether current line (without line number prefix) matches search expression:
cmd /V /C echo(^^!LINE^^!| > nul findstr /R /I /C:"!_SEARCH!" && (
rem /* Current line matches, so split it into two parts at certain expression (word);
rem the second part is the one that holds the number to replace later: */
set "AFTER=!LINE:*%_SPLIT%=!"
set "BEFORE=!LINE!|" & for /F "delims=" %%K in ("%_SPLIT%!AFTER!|") do set "BEFORE=!BEFORE:%%K=!"
rem /* Toggle delayed expansion to avoid troubles with exclamation marks `!`;
rem this requires `setlocal`/`endlocal` pairs, which localise environments;
rem hence use `for /F` to transport some values over `endlocal` barrier;
rem the temporary underscores `_` ensure none of the tokens appear empty: */
for /F "tokens=1* delims=| eol=|" %%G in ("_!BEFORE!|!AFTER!_") do (
rem // Split the second part at number:
for /F "tokens=1* delims=0123456789 eol=0" %%I in ("_!AFTER!_") do (
endlocal
set "FLAG=#"
set "BEFORE=%%G" & set "AFTER=%%H"
set "LEFT=%%I" & set "RIGHT=%%J"
setlocal EnableDelayedExpansion
rem // Append the part before the number to the first part:
set "BEFORE=!BEFORE:~1!%_SPLIT%!LEFT:~1!"
rem // Extract the number from the second part:
set "NUMBER=_!AFTER!|" & set "NUMBER=!NUMBER:*%%I=!" & set "NUMBER=!NUMBER:%%J|=!"
rem // Store the part after the number as the new second part:
set "AFTER=!RIGHT:~,-1!"
)
)
rem // Prompt user for new number (keep old one as per default):
set "ENTRY=!NUMBER!" & > con set /P ENTRY="Number (!ENTRY!): " && (
rem // Verify that entry is purely numeric (with white-spaces ignored):
set "ENTRY=!ENTRY: =!" & set "ENTRY=!ENTRY:%_T%=!"
(for /F "delims=0123456789 eol=0" %%K in ("!ENTRY!") do rem/) && >&2 (
echo Number entry is not purely numeric; keeping former value !NUMBER!.
) || set "NUMBER=!ENTRY!"
)
rem // Return line with the number exchanged:
echo(!BEFORE!!NUMBER!!AFTER!
) || (
rem // Current line does not match search expression, so return it unedited:
echo(!LINE:*:=!
)
endlocal
)
)
rem // Move temporary file onto input file, but only if a search expression has been found:
if defined FLAG (
> nul move /Y "%_TEMP%" "%_FILE%"
) else del "%_TEMP%"
endlocal
exit /B
There are some restrictions that come from the Windows Command Prompt, cmd:
437, 850, 1252, 65001, to mention some widespread ones; see the chcp command) to find the suitable conversion result;0x7F may become converted to something else, depending on the code page; if this is acceptable for you, you can again change the code page adequately;0x0D), followed by a line-feed (LF, code 0x0A), in short: CR+LF; files with Unix-style line-breaks (LF) are probably read correctly, but the output file will contain DOS/Windows-style line-breaks; files with MAC-style line-breaks (CR) cannot be processed;If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With