I'm writing a calculator on a cmd with enabled binary operations. I need to validate input data (remove letters, and other symbols that are not required for arithmetic operations)
#echo off
set data=
echo %* | findstr /R "\/\? ECHO" > nul
IF "%ERRORLEVEL%" EQU "0" goto printHelp
:main
set data= %data%%1
shift
if "%1" == "" (
echo %data% | findstr /R "^[0123456789*-+()/%!^_&|]*$" >nul 2>&1
if "%ERRORLEVEL%" EQU 0 (
echo Incorrect input data
exit /B
)
goto :result
) else (
goto :main
)
:result
set /a data="%data%"
echo %data%
exit /B
:printHelp
echo.
echo --------------------------------------------------
echo Using: calculator.bat [/?] [EXPRESSION]
echo helps you to consider arithmetic in Command Line
echo --------------------------------------------------
exit /B
My regular expression is not working. Also not considered to be a binary operation. What could be the problem?
Part 1 - Why your "regex is not working"
Your logic is wrong. FINDSTR sets ERRORLEVEL to 0 if there is a match, 1 if no match. Your regex is verifying that all characters are "valid", but your condition is treating a match as incorrect input.
Your IF statement uses quotes on one side, but not on the other. You must be consistent, otherwise it can never evaluate to TRUE.
Percent literals must be doubled within a batch script. Your regex has a percent literal that should be written as %%.
You use %ERRORLEVEL% in the same code block that sets the value. This cannot work because the value is expanded when the code block is parsed - before the value is set.
The simplest alternative is to use if errorlevel 1, which returns true if ERRORLEVEL is >= 1.
Another option is to enable delayed expansion with SETLOCAL ENABLEDELAYEDEXPANSION at top, and then use if !errorlevel! neq 0. But this would require that quoted ! literal in your regex be escaped as ^!, and ^ literal escaped as ^^.
My favorite option is to use the && and || conditional operators instead of IF.
findstr ... >nul && (match found statements) || (no match statements)
In your case, you want to take action if there was no match, so you only need the || operator.
Part 2 - Why your whole concept is not a good idea
Your validation is overly simplistic. Simply screening out invalid characters does not prevent errors. For example, 1**2 will result in an error, even though all characters are "valid". There are many other inputs with "valid" characters that would result in an error.
SET /A can work directly with environment variables. It knows how to access the value without you expanding the value in your code. This can be a powerful tool. A variable name used in a computation can include any character that is not an operator. So one can argue that there are no invalid characters for SET /A computations. Your exclusion of "invalid" characters prevents use of variables in computations.
Below is a simple batch calculator program I wrote some time ago. It is in an endless loop requesting input and displaying the result, until you enter a quit command. It supports all operators supported by SET /A.
It allows you to define and use variables in your expressions. The result of the most recent computation is always stored in a variable named #.
The calculator can display results as decimal, hexidecimal, or binary.
By default, it only displays the result of the last computation. It can be instructed to also display the value of all variables after each computation.
You can enter a command instead of a math computation. All commands begin with a \
\ Quit
\V Toggle variable listing ON or OFF
\D Decimal mode - results are displayed as decimal
\H Hex mode - results are displayed as hexidecimal
\B Binary mode - results are displayed as binary
\C X Clear variable X
\C * Clear all variables
\C X* Clear all variables that begin with X
Entering nothing will list all the currently defined variables.
Cleared variables are undefined. Note that an undefined variable has an implicit value of 0.
Here is the code:
#echo off
setlocal enableDelayedExpansion
for /f "delims==" %%v in ('set') do set %%v=
set __skip=#COMSPEC#PATHEXT#PROMPT#__mode#__str#__skip#__clr###__dispVars#
set __mode=Dec
set __dispVars=0
:top
echo:
set __str=
set /p "__str=%__mode%> "
if "!__str!"=="\" exit /b
if "!__str!"=="" call :dispVar # & call :dispVars & goto :top
if /i "!__str:~0,2!"=="\C" call :clearVars &goto :top
if /i "!__str!"=="\H" (set __mode=Hex) ^
else if /i "!__str!"=="\D" (set __mode=Dec) ^
else if /i "!__str!"=="\B" (set __mode=Bin) ^
else if /i "!__str!"=="\V" (set /a "__dispVars=^!__dispVars") ^
else set /a #=(!__str!)
call :dispVar #
if !__dispVars! gtr 0 call :dispVars
goto :top
:clearVars
for /f "delims=,; " %%v in ("!__str:~2!") do (
set __clr=%%v
if "!__clr:~-1!"=="*" (
set __clr=!__clr:~0,-1!
for /f "delims==" %%x in ('set !__clr!') do (
if "!__skip:#%%x#=!"=="!__skip!" set "%%x="
)
) else set "%%v="
)
call :dispVar #
call :dispVars
exit /b
:dispVars
setlocal
for /f "tokens=1,2 delims==" %%v in ('set') do if "!__skip:#%%v#=!"=="!__skip!" call :dispVar %%v
exit /b
:dispVar Var
setlocal
if !__mode!==Hex call :num2hex %1 disp
if !__mode!==Bin call :num2bin %1 disp
if !__mode!==Dec set /a disp=!%~1!
set var=%~1
if "!var:~0,6!"=="!var!" (
set "var=!var! ----------"
set "var=!var:~0,6!"
)
echo %var% = !disp!
exit /b
:num2hex NumVal RtnVar
setlocal enabledelayedexpansion
set hex=
set /a "dec=%~1"
set "map=0123456789ABCDEF"
for /l %%n in (1,1,8) do (
set /a "d=dec&15,dec>>=4"
for %%d in (!d!) do set "hex=!map:~%%d,1!!hex!"
)
(endlocal & rem return values
set %~2=%hex%
exit /b
)
exit /b
:num2bin NumVal RtnVar
setlocal enabledelayedexpansion
set bin=
set /a "dec=%~1"
for /l %%n in (1,1,32) do (
set /a "d=dec&1,dec>>=1"
set "bin=!d!!bin!"
)
(endlocal & rem return values
set %~2=%bin%
exit /b
)
exit /b
And here are the results of a short session:
D:\test>calculate.bat
Dec> 2*3
# ---- = 6
Dec> a=#+1
# ---- = 7
Dec>
# ---- = 7
a ---- = 7
Dec> b=(a+=5)*2
# ---- = 24
Dec> \v
# ---- = 24
a ---- = 12
b ---- = 24
Dec> c=b/3
# ---- = 8
a ---- = 12
b ---- = 24
c ---- = 8
Dec> \h
# ---- = 00000008
a ---- = 0000000C
b ---- = 00000018
c ---- = 00000008
Hex> \b
# ---- = 00000000000000000000000000001000
a ---- = 00000000000000000000000000001100
b ---- = 00000000000000000000000000011000
c ---- = 00000000000000000000000000001000
Bin> \
D:\test>
Related
I need to create a cmd script (and somehow I did) that extracts some lines of text from a series of files and puts them in a new txt file.
The source files are like this:
%
!
! AAA
!
! ------------------------ SOME TEXT ABCDEFGHIJKLMN --------------------------
!
! BBB
! ----------------------------------------------------------------------------
! T5 PUNTA ø 6.5/9.5~ $ 63~
! ----------------------------------------------------------------------------
! T12 PUNTA ø 2.5~ $ 39~
! ----------------------------------------------------------------------------
!
! SOME OTHER TEXT
!
! 1] ABC
! 2] DEF
! 3] ...
OTHER LINE 1
OTHER LINE 2
ETC
%
And the lines I need to extract are the ones between two "! ----------------------------------------------------------------------------" so, in this case, T5 PUNTA ø 6.5/9.5~ $ 63~ and T12 PUNTA ø 2.5~ $ 39~.
I was trying some regular expressions with findstr to match a line with ! only after the relevant lines, which indicates the end of the search, until I came up (by pure chance) with an instruction that matches all and only the lines that I need (luck, I guess).
The snippet is this:
#echo off
setlocal enabledelayedexpansion
if exist output.txt ( break > output.txt )
for /r <path> %%g in (<filename>) do (
...
for /f "tokens=* delims= " %%a in (%%g) do (
echo %%a | findstr /r /c:^\!$ >nul
if errorlevel 1 (...)
) else ( echo %%a >> srcoutput.txt
...
)
)
)
Please focus on the instruction echo %%a | findstr /r /c:^\!$ >nul.
This, for a reason I don't know, matches only the lines T5 PUNTA ø 6.5/9.5~ $ 63~ and T12 PUNTA ø 2.5~ $ 39~. Which is exactly what I want, but I don't know why it works!
Can someone help me understand why this simple expression ^\!$ works?
In my (wrong) understanding, it should match only a line with a single ! (which I had escaped, because otherwise it didn't work) at the beginning and at the end.
Thank you in advance
Actually the comand line:
echo %%a | findstr /r /c:^\!$ >nul
just returns lines that contain a $-character.
This is what happens, step by step:
the command line becomes parsed to (assuming %%a holds <expanded text>):
echo <expanded text> | findstr /r /c:\!$ >nul
so the (unquoted) caret (^) disappears as it is the escape character for cmd; since \ has no special meaning, you could just omit the ^ after all;
since delayed expansion is enabled (actually unnecessarily), the !-sign disappears, because there is only one, so the command line becomes:
echo <expanded text> | findstr /r /c:\$ >nul
the \-symbol acts as an escape character (though particularly for findstr!), so the $-sign loses its special meaning in regular expression (/R) mode (namely to anchor a match to the end of a line) and is therefore treated as a literal character;
the left side of the pipe passes on the text <expanded text> (with a trailing SPACE since there is one before the |), and the right side eventually searches for literal $-characters in that text;
You would achieve the exactly same result using the following command line instead:
echo %%a | findstr /C:$ > nul
though I would rather write it as:
echo(%%a| findstr /C:"$" > nul
to avoid the trailing SPACE and to safely echo any text.
For this task I would probably go for another approach (see all the explanatory rem remarks):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_ROOT=D:\Target\Path" & rem // (path to root directory)
set "_MASK=*.txt" & rem // (name or mask of files to process)
set "_SAVE=D:\Path\To\output.txt" & rem // (location of output file)
rem // Gather line-feed character:
(set ^"_LF=^
%= blank line =%
^")
rem // Gather carriage-return character:
for /F %%C in ('copy /Z "%~f0" nul') do set "_CR=%%C"
rem // Open output file only once and write to it:
> "%_SAVE%" (
rem // Find matching files and loop through them:
for /R "%_ROOT%" %%F in ("%_MASK%") do (
rem // Check for file existence (only necessary when a dedicated name is given):
if exist "%%~F" (
rem // Store path of current file:
set "FILE=%%~F"
rem // Toggle delayed expansion to avoid troubles with `!`:
setlocal EnableDelayedExpansion
rem // Remove remaining quotes (only necessary when a dedicated name is given):
set "FILE=!FILE:"=!
rem /* Do a multi-line search by `findstr`, which only returns the first line;
rem the searched string is:
rem # anchored to the beginning of a line,
rem # an `!`, a space and a `T`, then
rem # some arbitrary text (without line-breaks), then
rem # a line-break, then another `!` and a space, then
rem # a sequence of one or more `-`,
rem # anchored to the end of a line;
rem only the portion before the explicit line-break is then returned: */
findstr /R /C:"^^^! T.*~!_CR!!_LF!^! --*$" "!FILE!"
endlocal
)
)
)
endlocal
exit /B
This does not exactly search for lines between ! --- etc., but it searches for two adjacent lines where the first one begins with ! + SPACE + T and ends with ~, and the second one consists of ! + SPACE + a sequence of one or more -.
If the input file contains Unix-/Linux-style line-breaks rather than DOS-/Windows-style ones, replace !_CR!!_LF! in the findstr search string in the script by !_LF!.
I have decided to post this as a potential method of achieving your intented goal. It uses a different methodology from the currently accepted answer, the idea is to retrieve the ! ----etc. line numbers, then determine if the lines between any two of them have the required content. This means that it isn't looking to match specific content between those lines and should therefore work, whichever characters your strings are formed using.
#Echo Off
SetLocal EnableExtensions
Set "InFile=somefile.ext"
Set "OutFile=someoutfile.ext"
Set "$#="&For /F "Delims=:" %%G In (
'"%__AppDir__%findstr.exe /RNC:"^! --*$" "%InFile%""')Do (
Set /A _2=%%G-2&Call Set "$#= %%G %%$#%%"&Call Set "$2= %%_2%% %%$2%%")
If Not Defined $# Echo No Matches&%__AppDir__%timeout.exe -3&Exit /B
SetLocal EnableDelayedExpansion
For %%G In (%$2%)Do If "!$#: %%G =!"=="%$#%" Set "$2=!$2: %%G =!"
For %%G In (%$2%)Do Set /A _1=%%G+1&Set "$1= !_1! !$1!"
EndLocal&(For %%G In (%$1%)Do For /F "Tokens=1*Delims=]" %%H In (
'%__AppDir__%find.exe /V /N "" "%InFile%"^
^|%__AppDir__%findstr.exe "^\[%%G\]"')Do Echo %%I)>"%OutFile%"
GoTo :EOF
Just change your input file and output file names on lines 3 and 4, as required.
Please note that I'm unble to test this, so it may not work, or could possibly work in the wrong way. Please test it on files with various similar formats, before using it for real!
I try to write some simple program in windows batch file. This program is similar to some simple application from "C programming language" Kernighan and Ritchie.
The task of this program is to count char numbers and words numbers. Belove there is a source code
rem Char Number and words number
#echo off
cls
echo ===============================================================
echo input strin
set /P a=
::set variables
set Temp_str=%a%
set /A charcounter = 0
set /A wordscounter = 0
:loop
if defined Temp_str (
set /P actual_char=%Temp_str:~0,1%
if %actual_char%=="" ( set /A wordscounter+=1 )
set Temp_str=%Temp_str:~1%
set /A charcounter+=1;
goto loop
)
echo %a% %charcounter% %wordscounter%
There is error somewher but I can't find it. I don't know what is wrong. I actually start with batch windows programming.
To debug batch files always disable #echo off otherwise you're flying blind
From there you'll see the issue is on the line
if %actual_char%=="" ( set /A wordscounter+=1 )
You need to add quotes.
if "%actual_char%"=="" ( set /A wordscounter+=1 )
In addition there are other issues with the code:
1).
set /P actual_char=%Temp_str:~0,1%
Should not have the /p option as you're not wanting to prompt the user to enter the character.
2) Your word counter should be checking for spaces in addition to the blank string and you also should check what happens with the end of the first word.
rem Char Number and words number
rem #echo off
cls
echo ===============================================================
set /P a=input string:
::set variables
set Temp_str=%a%
set /A charcounter = 0
set /A wordscounter = 0
:loop
if "%Temp_str%" NEQ "" (
set actual_char=%Temp_str:~0,1%
if "%actual_char%"==" " ( set /A wordscounter+=1 )
set Temp_str=%Temp_str:~1%
set /A charcounter+=1;
goto loop
)
REM Increment word count for the final word
if "%a%" NEQ "" ( set /A wordscounter+=1 )
echo %a% %charcounter% %wordscounter%
I am working on a batch script to move files from one master directory which has 1000+ files to sub folders, according to the file name, sub folders have to be created and moved accordingly. Below is the scenario/ file name format.
title_or_work_done_by_user_name.xls
From this file name pattern, I have to pick "user_name" and create a folder for that user_name. I found similar code, but not able to break it exactly at the last 'by'.
#ECHO OFF
SETLOCAL
SET "sourcedir=E:\Source"
SET "destdir=E:\Destination"
FOR /f "tokens=2*delims='by_'" %%a IN ('dir /b /a-d "%sourcedir%\*by_*.xls" ') DO (
ECHO %%a
ECHO(MD "%destdir%\%%a" 2>nul
ECHO(MOVE "%sourcedir%\*by_%%a.xls" "%destdir%\%%a\")
pause
GOTO :EOF
Can some one please help me out in extracting 'user_name' by splitting it at the last occurrence of 'by_'.
Thanks in advance :)
The DELIMS option specifies a list of characters, not a string. So your FOR loop will split tokens at ' or _ or b or y. Also, you have no way of knowing what is the number for the last token. Your design is a dead end.
Option 1
Here is a pure batch solution that will do what you want. I use substitution to convert the file name into a pseudo path. It is then easy to pick off the desired name. Delayed expansion is used in order to access the value of a variable within the same loop (code block) that sets it. The only tricky part is toggling delayed expansion on and off as needed so as to preserve any !. A FOR variable containing the ! character will be corrupted if it is expanded while delayed expansion is enabled.
#echo off
setlocal disableDelayedExpansion
for %%F in (*_by_*.jpg) do (
%= Initialize name without extension =%
set "name=%%~nF"
%= Convert "Part1_by_Part2_by_Name" into "Part1\Part2\Name" =%
setlocal enableDelayedExpansion
for %%f in ("!name: - =\!") do (
%= Only execute endlocal on the first iteration =%
if "!!" equ "" endlocal
%= The name might contain a dot, so need name and extension =%
set "name=%%~nxf"
)
set "file=%%F"
setlocal enableDelayedExpansion
%= Hide error message if folder already exists =%
md "!name!" 2>nul
move "!file!" "!name!"
endlocal
)
Option 2
The logic is simpler if a subroutine is used, as it avoids delayed expansion issues. The CALL makes the code less efficient (slower), but that shouldn't be an issue for a task like this.
#echo off
setlocal disableDelayedExpansion
for %%F in (*_by_*.jpg) do call :moveFile "%%F"
exit /b
:moveFile
set "name=%~n1"
for %%F in ("%name:_by_=\%") do set "name=%%~nxF"
md "%name%" 2>nul
move %1 "%name%"
exit /b
Option 3
The simplest solution is to use my JREPL.BAT utility - a hybrid JScript/batch script that performs regex replacement. JREPL is pure script that runs natively on any Windows machine from XP onward.
#echo off
for /f "tokens=1,2 delims=: eol=:" %%A in (
'dir /b /a-d *_by_*.jpg ^| jrepl "^.*_by_(.*)\.jpg" "$&:$1" /i'
) do (
md "%%B" 2>nul
move "%%A" "%%B"
)
#ECHO OFF
SETLOCAL
FOR %%a IN (
title_or_work_done_by_user_name.xls
title_or_work_done_by_digby_hill.xls
title_or_work_done_by_hook_or_by_crook.xls
) DO CALL :process %%a
GOTO :eof
:process
SET "name=%~1"
:: This is the actual processing
ECHO processing "%name%"
SET "name=%name:_by_=.%"
:loop
FOR /f "tokens=1,2,3*delims=." %%p IN ("%name%") DO IF "%%s"=="" (SET "user_name=%%q") ELSE (
SET "name=%%q.%%r.%%s"&GOTO loop
)
ECHO extracted name is "%user_name%"
GOTO :EOF
I've chosen to use the string _by_ as the separator, since there are names that end "by".
Simply replace the string _by_ with a string that won't occur (or has a restricted use) in the filename. I chose . byt perhaps with sme modifications (like removing the extension from the name using %~n : could be used.
The reult is [string.]*required_name.xls
By repeatedly removing the first token using . as a separator, when there is no 4th+token, then the second token would be the required string.
I want to match all lines of the following text with FINDSTR /R
LABO_A =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = host01)(PORT = 1521))
(CONNECT_DATA =
(SERVICE_NAME = LABO)
)
)
I already tried What are the undocumented features and limitations of the Windows FINDSTR command?
Especially the "Searching across line breaks" part. But unfortunately it didn't work.
My approach is the following:
SETLOCAL
set LF=^
FOR /F %%A IN ('COPY /Z "%~dpf0" NUL') DO SET "CR=%%A"
SETLOCAL enableDelayedExpansion
FINDSTR /R "LABO_A.=.!CR!*!LF!.*(DESCRIPTION.=.!CR!*!LF!.*(ADDRESS.=.(PROTOCOL.=.TCP)(HOST.=.host01)(PORT.=.1521))!CR!*!LF!.*(CONNECT_DATA.=!CR!*!LF!.*(SERVICE_NAME.=.LABO)!CR!*!LF!.*)!CR!*!LF!.*)" %FINDPATH%
Am I missing something? Or is the batch regex simply not powerful enough to realize this?
SOLUTION:
The approach of #dbenham let me reconsider my regex-string. So I edited it to
FINDSTR /R /C:"LABO_A =!CR!*!LF!.*(DESCRIPTION =!CR!*!LF!.*(ADDRESS = (PROTOCOL = TCP)(HOST = host01)(PORT = 1521))!CR!*!LF!.*(CONNECT_DATA =!CR!*!LF!.*(SERVICE_NAME = LABO)!CR!*!LF!.*)!CR!*!LF!.*)" %FINDPATH% > NUL
I removed some unnecessary white spaces and adapted the parameters of FINDSTR.
Now it works.
Your regex is wrong. Your source lines end immediately after the =, but the extra . in your regex is looking for an additional character after the =.
It looks to me you are using . to represent white space. I think you would be better off using actual spaces, but then you need the /C option.
The following matches the lines successfully.
#echo off
SETLOCAL
set LF=^
FOR /F %%A IN ('COPY /Z "%~dpf0" NUL') DO SET "CR=%%A"
SETLOCAL enableDelayedExpansion
FINDSTR /R /C:"LABO_A =!CR!*!LF! *(DESCRIPTION =!CR!*!LF! *(ADDRESS = (PROTOCOL = TCP)(HOST = host01)(PORT = 1521))!CR!*!LF! *(CONNECT_DATA =!CR!*!LF! *(SERVICE_NAME = LABO)!CR!*!LF! *)!CR!*!LF! *)" test.txt
Note that even though all lines in the regex are matched, only the first line of the matching set is printed.
I suspect that the line breaks are not required in your configuration file. Here is another variation that allows for more variation in the white space.
#echo off
setlocal enableDelayedExpansion
set LF=^
FOR /F %%A IN ('COPY /Z "%~dpf0" NUL') DO SET "CR=%%A"
set "ws=[ !cr!!lf!]*"
FINDSTR /RX /C:"LABO_A =!ws!(DESCRIPTION =!ws!(ADDRESS = (PROTOCOL = TCP)(HOST = host01)(PORT = 1521))!ws!(CONNECT_DATA =!ws!(SERVICE_NAME = LABO)!ws!)!ws!)!ws!" test.txt
I also attempted to allow white space in every place I thought possible, but that exceeded FINDSTR's maximum REGEX string length.
Essentially, batch regex isn't powerful enough. SED would be better no doubt.
Nonetheless, here's a way to detect that a sequence of lines appears in a file. It's a little restricted, but should suffice for the sequence you've nominated. It assumes that leading spaces are not significant.
#ECHO OFF
SETLOCAL enabledelayedexpansion
FOR /f "delims==" %%a IN ('set l_ 2^>nul') DO "SET %%a="
SET /a lines=0
FOR /f "tokens=*" %%a IN (q19859936.txt) DO SET /a lines+=1&SET l_!lines!=%%a
SET hits=0
SET "stop="
FOR /f "tokens=*" %%a IN (q19859936.test) DO (
SET l_0=%%~a
CALL :test
IF DEFINED stop GOTO done
)
:done
IF DEFINED stop (ECHO FOUND ) ELSE (ECHO NOT FOUND)
GOTO :EOF
:test
SET /a hits+=1
ECHO IF NOT "!l_%hits%!"=="%l_0%"
IF NOT "!l_%hits%!"=="%l_0%" SET hits=0&IF %hits%==1 (GOTO :eof) ELSE (GOTO test)
IF %hits%==%lines% SET stop=Y
GOTO :eof
[edited code 20131111T1408Z - first FOR had tokens=2]
The initial FOR ensures that variables L_* are cleared.
The file q19859936.txt is read as the line-sequence-to-be-detected data.
q19859936.test is then examined. Each line is assigned to L_0 in turn and the internal subroutine :test will check to see whether it matches the next-line-expected.
The IF NOT statement is significant - and seemingly illogical (you'd need to add the /i switch to make it case-insensitive if you so want...) When batch parses the line, %hits% is replaced by the then-current value of hits and THEN the line is executed, so hits will be reset to 0 if ever a mismatch is found. If the HITS count WAS not 1, then the test is repeated. This takes care of the case
matches line 1
matches line 2
matches line 3
matches line 1
matches line 2
matches line 3
matches line 4
matches line 5
matches line 6
where the second "line 1" is encountered when "line 4" was expected. HITS is thus changed to 0, but it WAS 4 so execution passes back to :test and the test repeated with HITS=1.
Another approach could have been to read lines into another array (say L#*) and test that L_* matched L#*, for %LINES% entries. On no match, ripple-up and assign the next line read to L#!lines! ... but I thought of that later. Probably be easier and better, too - I'll leave it as an exercise for whoever may be interested.
This will work if you are after the LABO_A reference.
It uses a helper batch file called findrepl.bat from - https://www.dropbox.com/s/rfdldmcb6vwi9xc/findrepl.bat
Place findrepl.bat in the same folder as the batch file or on the path.
type "file.txt" | findrepl "^LABO_A =" /e:"^ \)"
i want to use my %variable% to manage the conditional clauses in a IF.. THEN.. ELSE in a batch file.
Something like the following:
set variable=%%homedrive%% EQU C:
if %variable% (
echo test ok
) else (
echo test fail
)
if i write on a cmd console:
set test=1 equ 1
if %test% echo OK
it works!
i'll use it in a for /f cicle:
this is my pseudo codethis is my pseudo code to correct
(
rem echo "%systemdrive%;;"
echo "%%COMPUTERNAME%% EQU [x];[some parameters1]"
echo "%%USERNAME%% NEQ [y];[some parameters2]"
echo "%%LOGONSERVER%% EQU [z];[some parameters3]"
[..]
) > "%temp%\CSG_fs.tmp"
[..]
for /f "usebackq tokens=1-2* delims=;" %%a in ("%temp%\CSG_fs.tmp") do (
set cond=%%a& set cond=!cond:~1!
set parm=%%b& set parm=!parm:~0,-1!
echo - cicle: "!cond!" --^> "!parm!"
call if !cond! call:CSG_sub_fs !parm!
echo - done
)
goto:eof
:CSG_sub_fs
[..]
goto:eof
--edit--
how can i use the variable !cond! to decide if execute the call to CSG_sub_fs?
call if !cond! call:CSG_sub_fs !parm!
does not work because it returns: "Can not find the batch label specified - IF"
and if i use
if !cond! call:CSG_sub_fs !parm!
it will say: "call:CSG_sub_fs not expected"
Well - there doesn't seem to be a question, so it's not that easy to answer.
You have a problem with
echo "^%COMPUTERNAME^% EQU [x];[some parameters1]"
because ^ does not escape % - % escapes % - use %%COMPUTERNAME%%...
(you should have been able to check this just by TYPEing "%temp%\CSG_fs.tmp"
Next problem is that
for /f "tokens=1-2* delims=; usebackq" %%a in (%temp%\CSG_fs.tmp) do (
may process the file %temp%\CSG_fs.tmp provided %temp%\CSG_fs.tmp contains no spaces, semicolons or commas. If it contains any of these deafult separators, or certain other characters with a special meaning, then you must enclose the filename in double-quotes "%temp%\CSG_fs.tmp"and use the usebackq option.
You've attempted to use usebackq but DELIMS must be the LAST option if it is used. Your code would set ";","","u","s","e","b","a","c","k" and "q" as delimiters.
Beyond that, perhaps if you explain what you intend to achieve, we'd be able to devise the appropriate code.
Try this:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
CLS
REM I'm setting these variables for testing.
REM That isn't ususally a good idea but the SETLOCAL
REM will ensure they are restored on exit
SET computername=[x]
SET logonserver=[z]
(
rem echo "%systemdrive%;;"
echo "%%COMPUTERNAME%% EQU [x];[some parameters1]"
echo "%%USERNAME%% NEQ [y];[some parameters2]"
echo "%%LOGONSERVER%% EQU [z];[some parameters3]"
) > "%temp%\CSG_fs.tmp"
for /f "usebackqtokens=1-2* delims=;" %%a in ("%temp%\CSG_fs.tmp") do (
set cond=%%a& set "cond=IF !cond:~1! CALL :csg_sub_fs "
set parm=%%b& set parm=!parm:~0,-1!
CALL :varcmd "!cond!" "!parm!"
)
GOTO :eof
:varcmd
%~1 %~2
GOTO :eof
:csg_sub_fs
ECHO parameters supplied to csg_sub_fs were: %*
GOTO :eof
I've forced the variablenames to match the conditions you've used in order to trigger the subroutine calls. Change as you need to prove your concept.
And dont worry about imperfect English. I'm sure I wouldn't do as well in your language!