Parse string using batch script

2

How can I parse string using batch script?

Goal is to save in a array everything under Import: and strip out #head for example --> //MPackages/Project/config/abc.txt and //Packages/Project/config/cde.txt.

test.txt:

Version: 4.5.0
Import:
   //MPackages/Project/config/abc.txt                       #head
   //Packages/Project/config/cde.txt                        #head
View:
  //MPackages/Project/config/ac.txt                     #head
  //Packages/Project/config/de.txt                      #head

My try:

@echo off

set buildlog="devel.p4inc"

setlocal EnableDelayedExpansion
for /F "tokens=*" %%A in  (devel.p4inc) do  (
  if /i "%%A"=="Import:" set "import=true"
  IF DEFINED import (echo %%A)
)

desired output

   //MPackages/Project/config/abc.txt 
   //Packages/Project/config/cde.txt

anything under Import:

Mihir

Posted 2015-05-01T17:29:39.933

Reputation: 27

For clarity's sake, what's wrong with what you've tried? What results do you get with it (right or wrong)? – Ƭᴇcʜιᴇ007 – 2015-05-01T17:38:42.770

result was wrong.. it is printing everything under Import:.. i would only like //MPackages/Project/config/abc.txt and //Packages/Project/config/cde.txt to be printed out.. – Mihir – 2015-05-01T17:48:03.923

Add the result you want to get – STTR – 2015-05-01T17:53:40.240

added to original question – Mihir – 2015-05-01T17:56:19.767

Answers

1

One of the main problems in your logic is that you set the "import" variable once if something is true, but never reset it, or undefined it if it's not true anymore. So after the first time it's set, it will remain "defined" for the rest of the loop.

My preference is to set the variable specifically (true or false). Set it to false to start, then set it to true as wanted, but then also ensure you set it back to false when you need to. Then, at each iteration of the loop check if the variable is specifically set to True or False instead of checking if it's just defined.

This code works for me based on your info/goals:

@echo off

setlocal EnableDelayedExpansion

set buildlog=test.txt
set import=false

for /F "tokens=*" %%A in (%buildlog%) do (
    if /i "%%A"=="Import:" (
        set import=true
    )
    if /i "%%A"=="View:" (
        set import=false
    )
    if !import!==true (
        if not "%%A"=="Import:" (
            for /F "tokens=1" %%B in ("%%A") do (
                echo %%B
            )
        )
    )
)

We purposefully set the "Import" variable (flag) to false to start.

First For-loop goes through each line in the file (test.txt in this example, as specified by the "buildlog" variable; note: you need to remove the quotes around the file name in the variable for it to work in the For-loop).

The first IF sees if the current line is the "Import:" line, and if so, it flips the "import" flag to true.

The next IF sees if the current line is the "View:" line, and if so, it flips the "import" flag (back to) to false, so that it stops processing each line.

The 3rd IF checks if that "import" flag is true, and if so, it processes the line.

If it's true then the nested (4th) IF then checks if the line is the actual "import:" line, and if not, displays the line (keeps it from showing the "Import:" line in the output).

The second For-loop goes through the line we want displayed, and pulls only the first Token set which is (just) the path you want, leaving off the #head.

More/related info:

Edit after comments:

To deal with the "View:" line if it has a version number after it you could modify the code to something like:

@echo off

setlocal EnableDelayedExpansion

set buildlog=test.txt
set import=false

for /F "tokens=*" %%A in (%buildlog%) do (
    for /F "tokens=1" %%B in ("%%A") do (
        if /i "%%B"=="Import:" (
            set import=true
        )
        if /i "%%B"=="View:" (
            set import=false
        )
        if !import!==true (
            if not "%%B"=="Import:" (
                for /F "tokens=1" %%C in ("%%A") do (
                    echo %%C
                )
            )
        )
    )
)

This added For-loop will pull the first token off the line to check if it's "View:" or "Import:" instead of checking the whole line. Effectively ignoring anything after the first space it encounters on the line to do the check.

Ƭᴇcʜιᴇ007

Posted 2015-05-01T17:29:39.933

Reputation: 103 763

Damn.. you are great.. nice explanation.. it is removing #head and but it is printing everything View: and things under views..if /i "%%A"=="View:" ( set import=false ) is not working.. – Mihir – 2015-05-01T18:40:52.073

Not sure what to tell you, it works here based on your example data. Are you sure the line in your actual data is actually just "View:", and there's no extra spaces or anything? Does the capitalization match etc.? Can you provide a copy of the actual data file you're running it against? – Ƭᴇcʜιᴇ007 – 2015-05-01T18:47:17.413

sorry actually i'm running any application where view is something like "View: 3.2.43" – Mihir – 2015-05-01T18:53:28.923

Ahh ok, I'll post a modified version that deals with that... – Ƭᴇcʜιᴇ007 – 2015-05-01T18:59:26.197

Thank you TECHIE007 for your help and great explanation... – Mihir – 2015-05-01T19:00:30.800

1

@echo off
for /F "usebackq tokens=1" %%A in  ("devel.p4inc") do  (
Set temp=False
if "%%A" == "View:" Goto Exit
if  not "%%A" == "Import:" if  not "%%A" == "Version:"  echo %%A
)
:Exit

kingpin

Posted 2015-05-01T17:29:39.933

Reputation: 11

1Could you explain this as well @kingpin? It would make your answer more helpful to future visitors if you did :) You can [edit] the answer to add a bit of explanation :) – ᔕᖺᘎᕊ – 2015-05-01T21:23:16.690

0

command-line:

powershell [string]$f=gc test.txt;$pL=$f.IndexOf('Import:')+7;$pR=$f.IndexOf('View:');$s=$f.Substring($pL,$pR-$pL);$s -split'#head'^|ac result.txt

powershell:

powershell ./parsefl.ps1

parsefl.ps1

[string]$f=gc test.txt;
$pL=$f.IndexOf('Import:')+'Import:'.Length;$pR=$f.IndexOf('View:');
$s=$f.Substring($pL,$pR-$pL);
$s -split'#head'|ac result.txt

STTR

Posted 2015-05-01T17:29:39.933

Reputation: 6 180