1

This is an add-on to my previous question:

How to search for line with Effective("flyer", 100%); in a file and get the number assigned to a variable?

The code I have so far is:

@echo off
set "Effective="
for /F "tokens=2 delims=%%) " %%I in ('%SystemRoot%\System32\find.exe /I "flyer" file.cfg') do set "Effective=%%I"
if defined Effective echo The effective value is: %Effective%

This code takes number 100 from line Effective("flyer", 100%); in file.cfg.

But what to do if there are two lines with flyer in file.cfg?

I have already tried it and this code takes the last flyer value 50.

Effective("flyer", 100%);

Effective("flyer", 50%);

How to choose between them?

The first code block containing first flyer is:

CreateWeaponType("jda.weapon.aatower")
{
  Style("Projectile");

  MaxRange(96);

  HorizAngle(90);
  HorizSeparation(180);
  VertAngle(0);
  VertSeparation(120);
  TurnRate(90);
  Speed(100);
  Fixed(1);


  Damage()
  {
    Amount(10);

    Effective("infantry", 0%);
    Effective("vehicle", 0%);
    Effective("structure", 0%);
    Effective("flyer", 100%);

    Effective("mine", 0%);
  }

  Projectile("jda.proj.aatower");
  Delay(1);
  FirePoints()
  {
    Add("HP-Fire1");
    Add("HP-Fire2");
    Add("HP-Fire3");
    Add("HP-Fire4");
  }
}

The second flyer is in:

CreateObjectType("jda.exp.aatower", "Explosion")
{
  MapObj()
  {
    Mesh();
    GenericFX()
    {
      Add("ExplosionObj::Explode", "jda.fx.aatower.exp");
    }
  }
  ExplosionObj()
  {
    Damage()
    {
      Amount(16);

      Effective("infantry", 0%);
      Effective("vehicle", 0%);
      Effective("structure", 0%);
      Effective("flyer", 50%);
      Effective("mine", 0%);
    }
    AreaInner(4);
    AreaOuter(4);
    Persist(0);
  }
}

How to set a different variable for each one?

Mofi
  • 46,139
  • 17
  • 80
  • 143

3 Answers3

2
@echo off
setlocal enabledelayedexpansion
set /a count=0
for /F "tokens=2 delims=%%) " %%I in ('%SystemRoot%\System32\find.exe /I "flyer"^<file.cfg') do set /a count+=1&set "Effective[!count!]=%%I"
echo %count% items found
if %count% gtr 0 set effective[

The critical line here is the setlocal enabledelayedexpansion line which invokes delayed expansion where the syntax !var! results in the value of var as it might change within a for loop.

Hence, as count starts at 0, should the appropriate line be detected then count is incremented and then effective[value of count] is set to the appropriate value.

After the for loop finishes, the count is shown (obviously, this line is optional).

The final set will simply display the value(s) that are set in the environment for values beginning effective[ - but only if count is greater than 0.

(untested)

Compo
  • 36,585
  • 5
  • 27
  • 39
Magoo
  • 77,302
  • 8
  • 62
  • 84
2

Here's an example:

@For /F "Tokens=1*" %%A In ('FindStr /I "Effective(\"flyer\"," "file.cfg"^|Find /V /N ""')Do @For /F "Tokens=2Delims=,%% " %%C In ("%%B")Do @Set "flyer%%A=%%C"
@Set flyer[
@Pause

The bottom two lines are included just to show you the variables with their respective value strings.

You could also split the long line at the top into three lines to help maintain reasonable line lengths for readability:

@For /F "Tokens=1*" %%A In ('FindStr /I "Effective(\"flyer\"," "file.cfg"^
 ^|Find /V /N ""')Do @For /F "Tokens=2Delims=,%% " %%C In ("%%B"
)Do @Set "flyer%%A=%%C")
@Set flyer[
@Pause

Please note that this answer provides no way of determining which percentage belongs with which particular section of the .cfg file:

Compo
  • 36,585
  • 5
  • 27
  • 39
1

The answers posted by Magoo and Compo are already wonderful solutions. So there is nothing more to contribute by me, except if you are interest in only the first flyer value. In this case a small modification of original code can be used to exit the loop with a jump to a label below the loop after having assigned first flyer number from file.cfg to the environment variable Effective.

@echo off
set "Effective="
for /F "skip=2 tokens=2 delims=%%) " %%I in ('%SystemRoot%\System32\find.exe /I "flyer" file.cfg') do set "Effective=%%I" & goto HaveValue
:HaveValue
if defined Effective echo The effective value is: %Effective%

find.exe outputs an empty line and and the line ---------- FILE.CFG which is the reason for using FOR option skip=2 to skip the first two lines to avoid assigning FILE.CFG to environment variable Effective.

It is of course also possible to rewrite the entire code on being interested only in first flyer value.

@echo off
for /F "tokens=2 delims=%%) " %%I in ('%SystemRoot%\System32\findstr.exe /R /I "effective.*flyer" file.cfg') do set "Effective=%%I" & goto HaveValue
echo No line with "flyer" found in "file.cfg"
goto :EOF

:HaveValue
echo The effective value is: %Effective%

This code uses findstr.exe instead of find.exe which does not output header lines. And a very simple regular expression search string is used now instead of just literal search string flyer.

But the provided batch files by Magoo and Compo are already fine on being really interested in both flyer numbers.

Mofi
  • 46,139
  • 17
  • 80
  • 143
  • Additional information, `%SystemRoot%\System32\findstr.exe` will output `---------- FILE.CFG` etc. as mentioned above, but that can easily be eliminated by using redirection, `%__AppDir__%find.exe /I "flyer" – Compo Apr 20 '19 at 18:59