First, the answer on the question: Yes, it is possible.
But I think, it would be additionally interesting for everybody reading the question, how to get the last SId
number. Well, it is really difficult with using just limited Windows command interpreter capabilities to get this number from a text file with unknown format of the data. For that reason this pure and poor task description was interesting for me and I took this coding challenge.
I created in C:\Temp
a file Test File.log
with following three lines:
For the first line we have SId = 23 and then,
the second line contains nothing interesting despite SId=x8434
;on third it's "! SId = 56, following SId=8434which ... SId34234 ... !" SId
The last line starts with a semicolon which is a problem on lines being parsed with FOR because of eol=;
being the default resulting in ignoring such lines by default.
The last line contains also double quotes which requires delayed environment variable expansion on processing this line, and two exclamation marks which can very easily result in replacing the two !
and everything between by nothing on processing this line with delayed expansion being enabled.
The last line contains also 4 times SId
. The first two SId
are with varying number of spaces around the equal sign, third SId
is without an equal sign and therefore to ignore, and after last SId
there is just a single space.
The batch code below is commented for interested readers, with the exception of the code block for determining the number from last valid SId
occurrence. That part of the code is really hard to explain for a beginner in batch programming. It is definitely easier to understand how this code part works by removing @echo off
from top of the batch file, run the batch file from within a command prompt window and look on the output command lines.
The ProcessLine
block with the FOR loop and the subroutine GetNumber
is executed with the example Test File.log
four times with the values:
= 56, following SId=8434which ... SId34234 ... !" SId
=8434which ... SId34234 ... !" SId
34234 ... !" SId
Note: Each Value
ends with a trailing space.
The batch code for this very generally described task:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "LogFile=C:\Temp\Test File.log"
if not exist "%LogFile%" goto EndBatch
rem Use command FINDSTR to search for all lines containing case-sensitive
rem the string "SId = " without or with spaces around the equal sign and
rem at least one digit. Output by FINDSTR are the lines matching this regular
rem expression with line number and a colon at beginning because of option /N.
rem The option /N is used to make sure that no line with SId starts with a
rem semicolon as those lines would be ignored by default by FOR. The last
rem line with a string matching this simple regular expression is assigned
rem to variable LastLine. Otherwise this environment variable deleted
rem before the loop still does not exist after the loop finished.
set "LastLine="
for /F "delims=" %%I in ('%SystemRoot%\System32\findstr.exe /N /R /C:"SId *= *[0123456789]" "%LogFile%"') do set "LastLine=%%I"
if not defined LastLine goto EndBatch
rem The last line contains perhaps multiple times an equal sign and perhaps
rem even multiple "SId" (secure identifier) strings. So it is necessary to
rem process this last line really the hard way. And it is better to process
rem the line perhaps containing also double quotes or other characters with
rem a special meaning for the Windows command interpreter using delayed
rem environment variable expansion.
setlocal EnableDelayedExpansion
set "Identifier="
:ProcessLine
set "Value=!LastLine:*SID=!"
if not defined Value goto LineProcessed
if "!Value!" == "!LastLine!" goto LineProcessed
for /F "tokens=1,2" %%A in ("!Value!") do (
set "LastID="
if "%%A" == "=" (
set "Number=%%B"
call :GetNumber
) else (
set "Number=%%A"
if "!Number:~0,1!" == "=" (
set "Number=!Number:~1!"
call :GetNumber
)
)
if defined LastID set "Identifier=!LastID!"
set "LastLine=!Value!"
goto ProcessLine
)
set "LastLine=!Value!"
goto ProcessLine
:GetNumber
if not defined Number goto :EOF
set "IsDigit=1"
for /F "delims=0123456789" %%I in ("!Number:~0,1!") do set "IsDigit=0"
if %IsDigit% == 0 goto :EOF
set "LastID=%LastID%%Number:~0,1%"
set "Number=!Number:~1!"
goto GetNumber
rem Pass the last found identifier from current environment with delayed
rem expansion to previous environment on restoring previous environment.
:LineProcessed
endlocal & set "Identifier=%Identifier%"
if not defined Identifier goto EndBatch
echo Last SId found: %Identifier%
rem Other command lines which process the found identifier.
:EndBatch
endlocal
The output of this batch file for example Test File.log
is:
Last SId found: 8434
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
echo /?
endlocal /?
findstr /?
for /?
goto /?
if /?
rem /?
set /?
setlocal /?
Single line with multiple commands using Windows batch file explains &
operator as used on one command line.