@ECHO Off
SETLOCAL
::
:: remove variables starting $
FOR /F "delims==" %%a In ('set $ 2^>Nul') DO SET "%%a="
:: evaluate command line. Structure is
:: %1 : filename to be analysed
:: %2 : tag to signal "new data item"
:: %..: other REQUIRED tags
:: then repeat
:: /opt optional tags
:: /block start-analysis tag
:: /seq tags in required output-sequence
::
SET "$filename=%~1"
IF NOT EXIST "%$filename%" ECHO "%~1" NOT found&GOTO :EOF
SET "$mode=tag"
:tagloop
SHIFT
SET "$=%~1"
IF NOT DEFINED $ GOTO process
IF %$:~0,1%==/ (SET "$mode=%$:~1%") ELSE (CALL SET "$%$mode%=%%$%$mode%%% %~1")
GOTO tagloop
:process
:: start mode OFF in block mode, on otherwise
:: establish tag1 (which signals start-of-next-data-item)
IF DEFINED block (SET "$mode=") ELSE (SET "$mode=Y")
FOR %%z IN (%$tag%) DO IF NOT DEFINED $tag1 SET "$tag1=%%z"
:: default output sequence is requiredtags optionaltags
IF NOT DEFINED $seq SET "$seq=%$tag% %$opt%"
CALL :zapvars
FOR /f "usebackqtokens=*" %%L IN ("%$filename%") DO (
FOR /f "tokens=1-3delims=<>" %%a IN ("%%L") DO IF "%%c"=="" (CALL :lonely "%%a") ELSE (CALL :triplet "%%a" "%%b" "%%c")
)
)
GOTO :eof
:: One parameter on line - may be start/end of block
:lonely
FOR %%p IN (%$block%) DO IF /i "%%p"=="%~1" (SET "$mode=Y"&CALL :zapvars) ELSE (
IF /i "/%%p"=="%~1" CALL :output&SET "$mode=")
GOTO :eof
:: presume 3 elements - tag data endtag
:triplet
FOR %%p IN (%$tag1%) DO IF /i "%~1"=="%%p" CALL :output
FOR %%p IN (%$tag% %$opt%) DO IF /i "%~1"=="%%p" SET "$$%%p=%~2"
GOTO :eof
:output
IF NOT DEFINED $mode GOTO zapvars
:: build line for outputting - IF all the required elements are present
FOR %%p IN (%$tag%) DO IF NOT DEFINED $$%%p GOTO zapvars
SET "$line="
FOR %%p IN (%$seq%) DO IF DEFINED $$%%p (CALL SET "$line=%%$line%%,%%$$%%p%%") ELSE (CALL SET "$line=%%$line%%,""")
ECHO %$line:~1%
GOTO zapvars
:zapvars
FOR %%z IN (%$tag% %$opt%) DO SET "$$%%z="
GOTO :eof
Well - likely there's some holes in this - so "for experimental purposes"
Run it as thisbatch filename requiredtags
If there are optional tags, then add /opt optionaltags
To set the output field sequence, add /seq tagsrequiredtobeoutput - by default, use requiredtags+optionaltags
To activate output only between starttag and /starttag then add /block tag
The processing is reasonably simple. The tag names are built into envvars starting $
- $tag, $seq etc. The lines are assumed to be either <tag>
, </endtag>
or <tag>data</endtag>
.
Beyond that, the process is controlled by $mode
(when set : output) which is switched by the processing of a block
tag. Data is accumulated into envvars $$tagname
and will only be output if the $mode
swich is set and there is a full set of required
tags. The first required
tag is special, it controls when a new data item is started (and starting a new data item implies that the previous item being accumulated gets output)
hence, the command
thisbatch q28540123.txt username passwrod /opt policyname groupname /seq policyname groupname username passwrod /block users
would extract data <users>..</users>
, requiring username passwrod
and optionally policyname groupname
and at each databreak on username
(the first-mentioned required element) would show data in the sequence policyname groupname username passwrod