for /f "skip=2 tokens=1,5" %%i in (list.txt) do (
echo %%j ^| findstr %string% >NUL
IF ERRORLEVEL 0 SET EXIT=0 ELSE SET EXIT=1
)
I feel something with batch syntax but I do not what exactly.
L.
try this:
IF not ERRORLEVEL 1 (SET EXIT=0) ELSE (SET EXIT=1)
errorlevel 0 is always true.
--
Regards,
Mic
So few lines. So many potential errors :)
Your fundamental error, as foxi as pointed out is
IF ERRORLEVEL n
is true if ERRORLEVEL is n OR GREATER THAN n.
After a FINDSTR, ERRORLEVEL will always be >=0
(There are circumstances documented in this group in the past where
ERRORLEVEL can be <0, but essentially - and certainly after FINDSTR - it
will be >=0 )
Second problem is that the IF ERRORLEVEL is in the loop and even after the
IF statement is corrected, it will be executed for EACH line of list.txt,
bar the first two which are SKIPped. The upshot is that the variable will be
set on the LAST line of the file.
This may be a problem or it may be what you want to do. If the problem is
"Does token 5 of the last line of the file contain %string% ?" then no doubt
it will work, but there are faster ways like
for /f "skip=2 tokens=1,5" %%i in (list.txt) do set var=%%j
echo %var%| findstr "%string%" >NUL
IF ERRORLEVEL 1 SET EXIT=1 ELSE SET EXIT=0
where the FINDSTR is only executed ONCE, not for EVERY line (bar the first
two)
If the problem is "Does token 5 of ANY line of the file contain %string% ?"
then the code will only work if this is true on the LAST line and you should
change the processing to
SET VAR=1
for /f "skip=2 tokens=1,5" %%i in (list.txt) do (
echo %%j ^| findstr %string% >NUL
IF not ERRORLEVEL 1 SET VAR=0
)
There is also no apparent error handling fo the cases that the file does not
exist or where it does not contain at least 3 lines - not possible to tell
with the one statement you've published.
Next problem is the use of EXIT as a variable name. It's valid, but since
EXIT is a keyword in batch, not a good idea to use it as a variable name.
Another problem is what happens if one of the processed lines in list.txt
doesn't have a token 5? The effect would be to execute
echo ^| findstr %string% >NUL
on that line. This may or may not be a problem. It's YOUR data...
Next little quibble is that you haven't quoted '%string%' in the FINDSTR.
This is again valid, but would draw the attention of an experienced eye as
it is unusual syntax.
Last is a matter of technique. I'd use
(SET VAR=)
for /f "skip=2 tokens=1,5" %%i in (list.txt) do (
echo %%j ^| findstr %string% >NUL
IF not ERRORLEVEL 1 SET VAR=%%j
)
This allows you to use
IF DEFINED VAR
to determine whether the string was found AND VAR will contain the ACTUAL
(last) string in which the target was found - which may or may not be
useful.
The advantage here is that IF DEFINED VAR works WITHIN the FOR loop on the
RUN-TIME value of VAR, which can be useful.
1>nul findstr "%pattrern%" list.txt && set exit=0 || set exit=1
Ummm - no.
Your code would find the pattern wherever it occurred in the file, even if
it was in the first two lines or not in the fifth token as the OP has
programmed.
And your code, if it worked as required, could be simplified to
findstr "%pattrern%" list.txt >nul
set /a exit=1-%errorlevel%
"billious" news:6_SdnSBGt-Pthg_W...@westnet.com.au...
> .. simplified to ...
> findstr "%pattrern%" list.txt >nul
> set /a exit=1-%errorlevel%
I don't view that simplification as an improvement because it often
leads to errors. When testing an error code it is too easy to add a line
after the statement and thereby change the error code before the test.
Also, "exit=1-%errorlevel%" requires that you know ALL error codes that
can be produced by the statement, and it might not be just 1 or 0.
MicroSoft does not often tell us such things. With the test done as
"01MDM" has shown everything is on one line and cannot be separated, any
error is correctly caught, and the variable "exit" is explicitly set to
a known value.
Frank
Before all, Thank you for deep analysys od my loop.
Whole description of my task:
In real, instead of list.txt there will command for Windows SSH client
which read list of allowed IP addresses from iptables on linux router.
Tha data is formated:
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
1 ACCEPT 0 -- 10.12.33.185 !10.0.0.0/8
2 ACCEPT 0 -- 10.12.35.136 !10.0.0.0/8
3 ACCEPT 0 -- 10.12.77.5 !10.0.0.0/8
4 ACCEPT 0 -- 10.12.32.89 !10.0.0.0/8
5 ACCEPT 0 -- 10.12.35.122 !10.0.0.0/8
6 ACCEPT 0 -- 10.12.35.121 !10.0.0.0/8
7 ACCEPT 0 -- 10.12.35.188 !10.0.0.0/8
8 ACCEPT 0 -- 10.12.33.182 !10.0.0.0/8
9 ACCEPT 0 -- 10.12.33.181 !10.0.0.0/8
10 ACCEPT 0 -- 10.12.32.88 !10.0.0.0/8
11 ACCEPT 0 -- 10.12.48.232 !10.0.0.0/8
12 ACCEPT 0 -- 10.12.35.217 !10.0.0.0/8
etc...
batch should be always started with single specific IP address as
parameter %1 and this is the %string% variable.
For now, batch should read ip address given in parameter %1, compare to
all lines and if match in some line (only in one because IP address
should not be in duplicit in the iptables). If (not) match to any line,
text message "IP address is (not) listed" will be batch result.
In the feature I plan to catch also "chain num" field for matched ip
address and perform some iptables manipulation based on "Chain num".
BUT WAIT!!!!! I do not want to simply get final solution of this task,
written by somebody from this group. I want to understood how to
specific elements of inside of batch working, so please be patient with
me ;-)
At first, I do not understand what is exact difference between two usage
of ERRORLEVEL:
1. IF ERRORLEVEL 1 SET ......
2. IF %ERRORLEVEL%==1 SET .....
As I feel out, the ERRORLEVEL variable is set after whole line of
commands is processed, instead after each command on line of commands.
I perform following series of commands on command line:
c:\scripts>echo a | findstr a >NUL & echo %errorlevel%
0
c:\scripts>echo a | findstr a >NUL & echo %errorlevel%
0
c:\scripts>echo a | findstr b >NUL & echo %errorlevel%
0
c:\scripts>echo a | findstr b >NUL & echo %errorlevel%
1
c:\scripts>echo a | findstr b >NUL & echo %errorlevel%
1
c:\scripts>echo a | findstr a >NUL & echo %errorlevel%
1
c:\scripts>echo a | findstr a >NUL & echo %errorlevel%
0
By my observation of this behaviour is the command set exitcode after
whole line is processed, and this is the reason why the line 3 of my
test produce errorlevel value 0 but line 4 produce value 1 regardless
the echoed litera was changed in the line 3. Therefor I have to catch
errorlevel value not in the same line in the batch where command is
processed even if something between () represent one logical line of
commands in the batch file.
Am I right??
P.L.
An error can be because of wrong "pattern" =)) You need not check
errorlevel, just use "&& success || failure"
When the line is interpreted, any %var% is replaced by the THEN-CURRENT
value of VAR, hence %errorlevel% in your tests is the value of ERRORLEVEL as
it was BEFORE the FINDSTR was executed.
IF ERRORLEVEL n works on the CURRENT value of ERRORLEVEL.
Try:
echo before:%errorlevel%&echo a|findstr "a" >nul &if errorlevel 1 (Echo
before:%errorlevel% after: 1 or greater) else (Echo before:%errorlevel%
after: 0 or less)
(all one line - it will no doubt be wrapped)
which should clarify matters.
Agreed.
Frank
What do you mean by "wrong pattern"
L.
Solved. problem was the escaped pipe ^| When I delete the escape
character, the batch will work fine.
L.
Wrong search conditions