Community discussions

MikroTik App
 
Tal
Frequent Visitor
Frequent Visitor
Topic Author
Posts: 57
Joined: Wed Jun 17, 2015 2:17 am

[SOLVED] Using Dynamic Variable Names

Sat Aug 15, 2015 5:45 am

Is there any way to use dynamic names for variables?

Ex:
:global VALUE true

:foreach varname in "VAR1\n\rVAR2\n\rVAR3" \
do={
	:global "$varname" $VALUE
}

I would think that the above code should work, but it doesn't, because :global doesn't like taking a variable name from a variable. Any way to get around this?
Last edited by Tal on Fri Aug 28, 2015 6:56 am, edited 1 time in total.
 
User avatar
favincen
just joined
Posts: 21
Joined: Mon Jun 08, 2015 1:56 pm
Location: Grenoble, France

Re: Using Dynamic Variable Names

Thu Aug 27, 2015 3:59 pm

This code doesn't work. But it may give a hint toward a solution :
 :foreach varname in={"VAR1" ; "VAR2" ; "VAR3"  } do={:parse ":global $varname \$VALUE" }
Hope it can help.
 
User avatar
favincen
just joined
Posts: 21
Joined: Mon Jun 08, 2015 1:56 pm
Location: Grenoble, France

Re: Using Dynamic Variable Names

Thu Aug 27, 2015 4:53 pm

Using ":execute" instead of ":parse", it works 8) :
:foreach varname in={"VAR1" ; "VAR2" ; "VAR3"  } do={:execute ":global $varname \$VALUE" }
 
Tal
Frequent Visitor
Frequent Visitor
Topic Author
Posts: 57
Joined: Wed Jun 17, 2015 2:17 am

Re: Using Dynamic Variable Names

Fri Aug 28, 2015 6:55 am

Using ":execute" instead of ":parse", it works 8) :
:foreach varname in={"VAR1" ; "VAR2" ; "VAR3"  } do={:execute ":global $varname \$VALUE" }
I used $VALUE instead of \$VALUE, but it worked perfectly.

Thanks guys.
 
User avatar
favincen
just joined
Posts: 21
Joined: Mon Jun 08, 2015 1:56 pm
Location: Grenoble, France

Re: Using Dynamic Variable Names

Fri Aug 28, 2015 11:26 am

I used $VALUE instead of \$VALUE, but it worked perfectly.
Hi Tal,

Without "\" it works for most values. But If VALUE contains, for example, a string with spaces or special characters, "$VALUE" won't work while "\$VALUE" will... :wink:

BTW, a warning: I may have missed something but AFAIK, if the ":execute" f command fails, you get no error message of any kind. :oops:

Fabrice
 
Tal
Frequent Visitor
Frequent Visitor
Topic Author
Posts: 57
Joined: Wed Jun 17, 2015 2:17 am

Re: Using Dynamic Variable Names

Fri Aug 28, 2015 7:01 pm

I used $VALUE instead of \$VALUE, but it worked perfectly.
Hi Tal,

Without "\" it works for most values. But If VALUE contains, for example, a string with spaces or special characters, "$VALUE" won't work while "\$VALUE" will... :wink:

BTW, a warning: I may have missed something but AFAIK, if the ":execute" f command fails, you get no error message of any kind. :oops:

Fabrice
It didn't seem to work for me when I used "\$VALUE", but I'll try again. Pretty useful bit of info - thanks.
 
Winand
just joined
Posts: 4
Joined: Fri Sep 12, 2014 5:39 pm

Re: Using Dynamic Variable Names

Sat Aug 04, 2018 1:13 pm

This code doesn't work. But it may give a hint toward a solution :

You just need square brackets:
foreach varname in={"VAR1"; "VAR2"; "VAR3"} do={[parse "global $varname true"]}
 
randomwalk
just joined
Posts: 10
Joined: Sun Apr 21, 2013 3:40 am
Location: Canada

Re: Using Dynamic Variable Names

Sat Apr 13, 2019 11:28 pm

   
Last edited by randomwalk on Wed Dec 16, 2020 9:45 am, edited 1 time in total.
 
randomwalk
just joined
Posts: 10
Joined: Sun Apr 21, 2013 3:40 am
Location: Canada

Re: Using Dynamic Variable Names

Wed Dec 16, 2020 9:44 am

Works with global, but not possible with local. Is the any solution for local variables?
Store the dynamically created local variables in an array.

{
    :local qty 9;           # number of variables to create
    :local varname "myvar"; # name for the variables

    :local myarray [:toarray ""];            # create empty array
    :for i from=1 to=$qty do={
        :local tmp ($varname . [:tostr $i]); # dynamically construct name of the variable
        :set ($myarray->$tmp) "";            # push the newly created variable into the array
    }
# setting the variables
    :set ($myarray->"myvar1") "plaintext"
    :set ($myarray->"myvar2") {"abc"}
    :set ($myarray->"myvar3") 
    :set ($myarray->"myvar4") true
    :set ($myarray->"myvar5") 127.0.0.1
    :set ($myarray->"myvar6") 23:59:59
    :set ($myarray->"myvar7") 192.168.88.0/24
    :set ($myarray->"myvar8") ::ffff:192.0.2.128
    :set ($myarray->"myvar9") 2001:0DB8:0000:000b::/64

# reading the variables
    :put ( "myvar1=" . ($myarray->"myvar1") . "   type=" . [ :typeof ($myarray->"myvar1") ] )
    :put ( "myvar2=" . ($myarray->"myvar2") . "   type=" . [ :typeof ($myarray->"myvar2") ] )
    :put ( "myvar3=" . ($myarray->"myvar3") . "   type=" . [ :typeof ($myarray->"myvar3") ] )
    :put ( "myvar4=" . ($myarray->"myvar4") . "   type=" . [ :typeof ($myarray->"myvar4") ] )
    :put ( "myvar5=" . ($myarray->"myvar5") . "   type=" . [ :typeof ($myarray->"myvar5") ] )
    :put ( "myvar6=" . ($myarray->"myvar6") . "   type=" . [ :typeof ($myarray->"myvar6") ] )
    :put ( "myvar7=" . ($myarray->"myvar7") . "   type=" . [ :typeof ($myarray->"myvar7") ] )
    :put ( "myvar8=" . ($myarray->"myvar8") . "   type=" . [ :typeof ($myarray->"myvar8") ] )
    :put ( "myvar9=" . ($myarray->"myvar9") . "   type=" . [ :typeof ($myarray->"myvar9") ] )
}

 
output:
[admin@rb] >
myvar1=plaintext type=str
myvar2=abc type=array
myvar3= type=nothing
myvar4=true type=bool
myvar5=127.0.0.1 type=ip
myvar6=23:59:59 type=time
myvar7=192.168.88.0/24 type=ip-prefix
myvar8=::ffff:192.0.2.128 type=ip6
myvar9=2001:db8:0:b::/64 type=ip6-prefix
 
iamarpit
just joined
Posts: 2
Joined: Fri Nov 26, 2021 4:07 pm

Re: Using Dynamic Variable Names

Fri Nov 26, 2021 4:41 pm

You just need square brackets:
foreach varname in={"VAR1"; "VAR2"; "VAR3"} do={[parse "global $varname true"]}
yeah but this doesn't work in this setting, if you put space in the values
foreach key,value in={"VAR1"="foo with space"; "VAR2"="bar"} do={[parse "global $key $value"]}
 
PackElend
Member Candidate
Member Candidate
Posts: 269
Joined: Tue Sep 29, 2020 6:05 pm

Re: Using Dynamic Variable Names

Tue Mar 29, 2022 9:47 am

I hope that thread is still active as I have a similar challenge
[admin@MikroTik] > :global vlancommon {id=100; name="VLAN_COMMON" ;  comment="COMMON SERVICES AND DEVICES / OFFICE"      }
[admin@MikroTik] > :put ($vlancommon)
comment=COMMON SERVICES AND DEVICES / OFFICE;id=100;name=VLAN_COMMON
[admin@MikroTik] > :put ($vlancommon->"name")
vlancommon 
[admin@MikroTik] > :put ([ :toarray "UP, vlancommon  ,KIDS" ]->1)
vlancommon 
[admin@MikroTik] > :put (:parse "\$([ :toarray "UP, vlancommon  ,KIDS" ]->1)"->"name")
comment=COMMON SERVICES AND DEVICES / OFFICE;id=100;name=VLAN_COMMON
but I would expect
VLAN_COMMON
in the last line.

When I start moving around the quotes, the result is even weirder.
Any idea what the last command has to look like to get the second element of the array vlancommon ?

Last but not least, how to modify when I going to use capital later and/or symbols in the variable name and/or array key name so that they have to be put in quotes?

thx
stefan
 
PackElend
Member Candidate
Member Candidate
Posts: 269
Joined: Tue Sep 29, 2020 6:05 pm

Re: Using Dynamic Variable Names

Tue Mar 29, 2022 6:13 pm

could solve it:
had do add another pair of (), to enclose the parse command
Any idea what the last command has to look like to get the second element of the array vlancommon ?
:put ( ( :parse "\$([ :toarray "UP, vlancommon  ,KIDS" ]->1)" ) -> "name") 
.
and pair of \"
Last but not least, how to modify when I going to use capital later and/or symbols in the variable name and/or array key name so that they have to be put in quotes?
:put ( ( :parse "\$\"([ :toarray "UP, vlancommon  ,KIDS" ]->1)\"" )->"name")
Last edited by PackElend on Wed Mar 30, 2022 1:09 pm, edited 1 time in total.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: [SOLVED] Using Dynamic Variable Names

Tue Mar 29, 2022 8:01 pm

Returning to OP question, is simple:
viewtopic.php?p=879152#p879152

The soluction is:

REX code

:global variablename "test"

# Create or set a value (on same command)
[:parse ":global $variablename \"REX1\""]

:put $test

# Set a value (or simply apply previous command)
[:parse "global $variablename;:set $variablename \"REX2\""]

:put $test

# For read the variable inside another declared variable:
:global testx
[:parse "global $variablename;:global testx \$$variablename"]

:put $testx
 
PackElend
Member Candidate
Member Candidate
Posts: 269
Joined: Tue Sep 29, 2020 6:05 pm

Re: Using Dynamic Variable Names

Wed Mar 30, 2022 1:40 pm

and pair of \"
Last but not least, how to modify when I going to use capital later and/or symbols in the variable name and/or array key name so that they have to be put in quotes?
:put ( ( :parse "\$\"([ :toarray "UP, vlancommon  ,KIDS" ]->1)\"" )->"name")
I made an error here; did not test "vlan_common".
Any idea how to make
:put ( ( :parse "\$\"([ :toarray "UP, vlan_common  ,KIDS" ]->1)\"" )->"name")
work?
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: [SOLVED] Using Dynamic Variable Names

Wed Mar 30, 2022 2:51 pm

for example, start to remove all significant spaces:
:put ">$([:toarray "UP, vlancommon  ,KIDS"]->1)<"
>vlancommon  <
:put ">$([:toarray "UP,vlancommon,KIDS"]->1)<"
>vlancommon<
 
PackElend
Member Candidate
Member Candidate
Posts: 269
Joined: Tue Sep 29, 2020 6:05 pm

Re: [SOLVED] Using Dynamic Variable Names

Wed Mar 30, 2022 3:10 pm

for example, start to remove all significant spaces:
:put ">$([:toarray "UP, vlancommon  ,KIDS"]->1)<"
>vlancommon  <
:put ">$([:toarray "UP,vlancommon,KIDS"]->1)<"
>vlancommon<
try the same but replace vlancommon by vlan_common
result shall be:
VLAN_COMMON
from
[admin@MikroTik] > :global "vlan_common" {id=100; name="VLAN_COMMON" ;  comment="COMMON SERVICES AND DEVICES / OFFICE"      }
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: [SOLVED] Using Dynamic Variable Names

Wed Mar 30, 2022 3:10 pm

whu replace "vlancommon by vlan_common"?
the problem are the spaces between elements on array....

and parse do not give results, you must USE parse...

:global vlancommon {id=100;name="VLAN_COMMON";comment="COMMON SERVICES AND DEVICES / OFFICE"}
:put ($vlancommon)
:put ($vlancommon->"name")
:put ([:toarray "UP,vlancommon,KIDS"]->1)
:global testx
[:parse "global vlancommon;:global testx (\$$([:toarray "UP,vlancommon,KIDS"]->1)->\"id\")"]
:put $testx
[:parse "global vlancommon;:global testx (\$$([:toarray "UP,vlancommon,KIDS"]->1)->\"name\")"]
:put $testx
[:parse "global vlancommon;:global testx (\$$([:toarray "UP,vlancommon,KIDS"]->1)->\"comment\")"]
:put $testx

output code

[mikro@tik] > :global vlancommon {id=100;name="VLAN_COMMON";comment="COMMON SERVICES AND DEVICES / OFFICE"}
[mikro@tik] > :put ($vlancommon)
comment=COMMON SERVICES AND DEVICES / OFFICE;id=100;name=VLAN_COMMON
[mikro@tik] > :put ($vlancommon->"name")
VLAN_COMMON
[mikro@tik] > :put ([:toarray "UP,vlancommon,KIDS"]->1)
vlancommon
[mikro@tik] > :global testx
[mikro@tik] > [:parse "global vlancommon;:global testx (\$$([:toarray "UP,vlancommon,KIDS"]->1)->\"id\")"]
[mikro@tik] > :put $testx
100
[mikro@tik] > [:parse "global vlancommon;:global testx (\$$([:toarray "UP,vlancommon,KIDS"]->1)->\"name\")"]
[mikro@tik] > :put $testx
VLAN_COMMON
[mikro@tik] > [:parse "global vlancommon;:global testx (\$$([:toarray "UP,vlancommon,KIDS"]->1)->\"comment\")"]
[mikro@tik] > :put $testx
COMMON SERVICES AND DEVICES / OFFICE
[mikro@tik] > 
 
PackElend
Member Candidate
Member Candidate
Posts: 269
Joined: Tue Sep 29, 2020 6:05 pm

Re: [SOLVED] Using Dynamic Variable Names

Wed Mar 30, 2022 3:17 pm

I got
[mikro@tik] > :global vlancommon {id=100;name="VLAN_COMMON";comment="COMMON SERVICES AND DEVICES / OFFICE"}

but not
[mikro@tik] > :global "vlan_common" {id=100;name="VLAN_COMMON";comment="COMMON SERVICES AND DEVICES / OFFICE"}
regardless the spaces.

The problem is Operations with Arrays - Manual:Scripting - MikroTik Wiki
Warning: Key name in array contains any character other than lowercase character, it should be put in quotes
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: [SOLVED] Using Dynamic Variable Names

Wed Mar 30, 2022 3:20 pm

Why you mix the cards?
I talk about spaces on array elements, not underscores....
 
PackElend
Member Candidate
Member Candidate
Posts: 269
Joined: Tue Sep 29, 2020 6:05 pm

Re: [SOLVED] Using Dynamic Variable Names

Wed Mar 30, 2022 3:24 pm

Why you mix the cards?
I talk about spaces on array elements, not underscores....
because I would like to know how to deal with:
:global "vlan_common" {id=100;name="VLAN_COMMON";comment="COMMON SERVICES AND DEVICES / OFFICE"} #variable has to be quoted
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: [SOLVED] Using Dynamic Variable Names

Wed Mar 30, 2022 3:28 pm

ah, on this way, obvious ;)

:global "vlan_common" {id=100;name="VLAN_COMMON";comment="COMMON SERVICES AND DEVICES / OFFICE"}
:put ($"vlan_common")
:put ($"vlan_common"->"name")
:put ([:toarray "UP,vlan_common,KIDS"]->1)
:global testx
[:parse ("global \"vlan_common\";:global testx (\$\"$([:toarray "UP,vlan_common,KIDS"]->1)\"->\"id\")")]
:put $testx
[:parse ("global \"vlan_common\";:global testx (\$\"$([:toarray "UP,vlan_common,KIDS"]->1)\"->\"name\")")]
:put $testx
[:parse ("global \"vlan_common\";:global testx (\$\"$([:toarray "UP,vlan_common,KIDS"]->1)\"->\"comment\")")]
:put $testx

output code

[mikro@tik] > :global "vlan_common" {id=100;name="VLAN_COMMON";comment="COMMON SERVICES AND DEVICES / OFFICE"}
[mikro@tik] > :put ($"vlan_common")
comment=COMMON SERVICES AND DEVICES / OFFICE;id=100;name=VLAN_COMMON
[mikro@tik] > :put ($"vlan_common"->"name")
VLAN_COMMON
[mikro@tik] > :put ([:toarray "UP,vlan_common,KIDS"]->1)
vlan_common
[mikro@tik] > :global testx
[mikro@tik] > [:parse ("global \"vlan_common\";:global testx (\$\"$([:toarray "UP,vlan_common,KIDS"]->1)\"->\"id\")")]
[mikro@tik] > :put $testx
100
[mikro@tik] > [:parse ("global \"vlan_common\";:global testx (\$\"$([:toarray "UP,vlan_common,KIDS"]->1)\"->\"name\")")]
[mikro@tik] > :put $testx
VLAN_COMMON
[mikro@tik] > [:parse ("global \"vlan_common\";:global testx (\$\"$([:toarray "UP,vlan_common,KIDS"]->1)\"->\"comment\")")]
[mikro@tik] > :put $testx
COMMON SERVICES AND DEVICES / OFFICE
[mikro@tik] > 
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: [SOLVED] Using Dynamic Variable Names

Wed Mar 30, 2022 3:32 pm

xxx
Last edited by rextended on Wed Mar 30, 2022 3:35 pm, edited 2 times in total.
 
PackElend
Member Candidate
Member Candidate
Posts: 269
Joined: Tue Sep 29, 2020 6:05 pm

Re: [SOLVED] Using Dynamic Variable Names

Wed Mar 30, 2022 3:34 pm

great :)
may you explain why
[:parse ("global \"vlan_common\";:global testx (\$\"$([
is necessary?

"global \"vlan_common\"
--> (evl /globalname=$vlan_common)
what happens next?

in particular (\$\"$
as I would expect that
:put ( ( :parse ("\$\"vlan_common\" ") ) )
gives the content of global "vlan_common"
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: [SOLVED] Using Dynamic Variable Names

Wed Mar 30, 2022 3:35 pm

All this is just for example, just to make your idea work, but is better do more "polite" code....

for example this is really hard to read and understand...
[:parse ("global \"vlan_common\";:global testx (\$\"$([:toarray "UP,vlan_common,KIDS"]->1)\"->\"name\")")]

something like this is better (example not tested):
:global readfromthis ([:toarray "UP,vlan_common,KIDS"]->1)
:global readthisfield "name"
[:parse ("global \"vlan_common\";:global testx (\$\"$readfromthis\"->\"$readthisfield\")")]
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: [SOLVED] Using Dynamic Variable Names

Wed Mar 30, 2022 3:38 pm

>>>great :)
>>>may you explain why
>>>[:parse ("global \"vlan_common\";:global testx (\$\"$([
>>>is necessary?
Because you must declare the variable used or do not work

>>>"global \"vlan_common\"
>>> --> (evl /globalname=$vlan_common)
>>>what happens next?
I do not go inside how internally the script are converted and run, if you obtain "evl" as results, probably you use ":parse" on wrong way
":parse" must be executed, not readed or assigned....

>>>in particular (\$\"$
>>>as I would expect that
>>>:put ( ( :parse ("\$\"vlan_common\" ") ) )
>>>gives the content of global "vlan_common"
again, ":put" can not read ":parse" as expected from you...
 
PackElend
Member Candidate
Member Candidate
Posts: 269
Joined: Tue Sep 29, 2020 6:05 pm

Re: [SOLVED] Using Dynamic Variable Names

Wed Mar 30, 2022 4:09 pm

>>>in particular (\$\"$
>>>as I would expect that
>>>:put ( ( :parse ("\$\"vlan_common\" ") ) )
>>>gives the content of global "vlan_common"
again, ":put" can not read ":parse" as expected from you...
but
[admin@MikroTik] <SAFE> :put (  :parse ("$(vlancommon)") )
comment=COMMON SERVICES AND DEVICES / OFFICE;id=100;name=VLAN_COMMON
works
 
PackElend
Member Candidate
Member Candidate
Posts: 269
Joined: Tue Sep 29, 2020 6:05 pm

Re: [SOLVED] Using Dynamic Variable Names

Wed Mar 30, 2022 4:12 pm

>>>great :)
>>>may you explain why
>>>[:parse ("global \"vlan_common\";:global testx (\$\"$([
>>>is necessary?
Because you must declare the variable used or do not work
declaration is done in line one, so why doing it again?
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: [SOLVED] Using Dynamic Variable Names

Wed Mar 30, 2022 5:58 pm

because every time you ":parse", is like you start another program,
what is do with previous ":parse" is lost
with ":global variablename" you instruct the system than you want use (already created or not) the variable "variablename"
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: [SOLVED] Using Dynamic Variable Names

Wed Mar 30, 2022 6:04 pm

>>>in particular (\$\"$
>>>as I would expect that
>>>:put ( ( :parse ("\$\"vlan_common\" ") ) )
>>>gives the content of global "vlan_common"
again, ":put" can not read ":parse" as expected from you...
but
[admin@MikroTik] <SAFE> :put (  :parse ("$(vlancommon)") )
comment=COMMON SERVICES AND DEVICES / OFFICE;id=100;name=VLAN_COMMON
works
when you write ":put (:parse ...)" on that way, simply the script convert vlancommon value (array) to "instructions" and the result is "comment...." (because internally the arrays are sort)
please do not give "but", only questions.
 
PackElend
Member Candidate
Member Candidate
Posts: 269
Joined: Tue Sep 29, 2020 6:05 pm

Re: [SOLVED] Using Dynamic Variable Names

Wed Mar 30, 2022 6:16 pm

please do not give "but", only questions.
will do

I was able to proceed thx to your comments, some questions are remaining.
I will add code later or tomorrow (hopefully) with the full code
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: [SOLVED] Using Dynamic Variable Names

Wed Mar 30, 2022 6:26 pm

I do not want be unpolite "but" for me is hard to explain, I'm not english :)
 
PackElend
Member Candidate
Member Candidate
Posts: 269
Joined: Tue Sep 29, 2020 6:05 pm

Re: [SOLVED] Using Dynamic Variable Names

Fri Apr 01, 2022 11:04 pm

travelling was more time-consuming than expected but here we go, my configuration/script
I modified your code slightly:
- keeping space works well and readability is maintained
- some variables can be local scope but not all, whyever?
    # name the device being configured
  /system identity set name="AP+ES_GF_MT-hAP-ac3"

  # create one bridge, with defaults only
  /interface bridge 
    add name=bridge-VLANs
  
  # add VLANs
  /interface vlan
    add interface=bridge-VLANs   vlan-id=999   name=VLAN_MGMT   comment="NETWORK DEVICES MANAGEMENT VLAN"	

  # VLAN interface for L3 Management Access
  /ip address  
    add address=10.10.9.001/24   interface=VLAN_MGMT   comment="NETWORK DEVICES MANAGEMENT VLAN"    --> CR_2B_MT-CCR1009-8G-1S-1S+      		
    add address=10.10.9.002/24   interface=VLAN_MGMT   comment="NETWORK DEVICES MANAGEMENT VLAN"    --> CS-PoE_2B_MT-CRS328-24P-4S+

  # The route to the router to allow L3 communication. 
  /ip route   
    add gateway=10.10.9.1   distance=1 
	
  # DNS server, to allow ROS to resolve DNS queries from the CPUto fetch updates etc.  
  /ip dns 
    set allow-remote-requests=no   servers="10.10.9.1"

  #ES_GF-E_MT-hEX-S
  /interface ethernet  
    set comment="TP, VLAN-TRUNK TO CORE-SWITCH-SFP" 	        [find name=sfp1]
    set comment="UP, don't touch (temporarily)"                 [find name=ether1]
    set comment="UP, VLAN_USER1, OFFICE, UNMANAGED SWITCH"      [find name=ether2]
    set comment="UP, VLAN_USER2, KIDS"                          [find name=ether3]  
    set comment="UP, VLAN_USER2, LIVING ROOM"                   [find name=ether4]
	set comment="UP, don't touch (temporarily)"                 [find name=ether5]
	
## START OF SCRIPT
#creating variable per VLAN and other variables
  :global "VLAN_BKHOLE" { vlanid=001; name="VLAN_BKHOLE" ;  comment="BLACKHOLE"                                 }
  :global "VLAN_SYS"    { vlanid=008; name="VLAN_SYS"    ;  comment="SYS"                                       }
  :global "VLAN_GUEST"  { vlanid=011; name="VLAN_GUEST"  ;  comment="GUEST"                                     }
  :global "VLAN_USER1"  { vlanid=110; name="VLAN_USER1"  ;  comment="USER 1,all devices in one vlan"            }
  :global "VLAN_USER2"  { vlanid=120; name="VLAN_USER2"  ;  comment="USER 2,all devices in one vlan"            }
  :global filterUP "^UP, VLAN_USER"
  :global BridgeName  "bridge-VLANs"
  :global result


#show configuration before script execution  
  interface ethernet print where comment~"^UP."
  interface bridge port print

#clear anything in /interface bridge port if there is an existing configuration   
  :put "CLEAR EXISTING BRIDGE PORT CONFIGURATION 
  :foreach Interface in=[ /interface bridge port find ] do={ / 
    /interface bridge port remove $Interface
  }
  
#show that /interface bridge port is empty   
  /interface bridge port print

#add Bridge Ports according to the comment of the interfaces. PVID is set as well. 
  :put "STARTING SCRIPT-BASED BRIDGE PORT CREATION
  :foreach Interface in=[ /interface ethernet find where comment~$filterUP ] do={ / 
    :local readcomment ( [ :toarray ([/interface ethernet get $Interface]->"comment" ) ]->1 )
    :local readthisfield "vlanid"
    [:parse ("global \"$readcomment\";:global result (\$\"$readcomment\"->\"$readthisfield\")")]
    /interface bridge port add interface=$Interface bridge=$BridgeName pvid=$result 
    }
  
"show result
  :put "SHOW RESULTS"
  /interface ethernet print where comment~"^UP,"
  /interface bridge port print
  /interface bridge port print where pvid=110
  /interface bridge port print where pvid=120
and the reduced code generated OUTPUT:
/interface ethernet print where comment~"^UP,"
Flags: R - RUNNING; S - SLAVE
Columns: NAME, MTU, MAC-ADDRESS, ARP, SWITCH
#    NAME     MTU  MAC-ADDRESS        ARP      SWITCH 
;;; UP, don't touch (temporarily)
0 R  ether1  1500  08:55:31:0F:52:97  enabled  switch1
;;; UP, VLAN_USER1, OFFICE, UNMANAGED SWITCH
1  S ether2  1500  08:55:31:0F:52:98  enabled  switch1
;;; UP, VLAN_USER2, KIDS
2  S ether3  1500  08:55:31:0F:52:99  enabled  switch1
;;; UP, VLAN_USER2, LIVING ROOM
3  S ether4  1500  08:55:31:0F:52:9A  enabled  switch1
;;; UP, don't touch (temporarily)
4    ether5  1500  08:55:31:0F:52:9B  enabled  switch1

CLEAR EXISTING BRIDGE PORT CONFIGURATION 

STARTING SCRIPT-BASED BRIDGE PORT CREATION

SHOW RESULTS

/interface ethernet print where comment~"^UP,"
Flags: I - INACTIVE; H - HW-OFFLOAD
Columns: INTERFACE, BRIDGE, HW, PVID, PRIORITY, PATH-COST, INTERNAL-PATH-COST, HORIZON
#    INTERFACE  BRIDGE        HW   PVID  PRIORITY  PATH-COST  INTERNAL-PATH-COST  HORIZON
0 IH ether2     bridge-VLANs  yes   110  0x80             10                  10  none   
1 IH ether3     bridge-VLANs  yes   120  0x80             10                  10  none   
2 IH ether4     bridge-VLANs  yes   120  0x80             10                  10  none   

[admin@MikroTik] /interface/mesh>   /interface bridge port print where pvid=110
Flags: I - INACTIVE; H - HW-OFFLOAD
Columns: INTERFACE, BRIDGE, HW, PVID, PRIORITY, PATH-COST, INTERNAL-PATH-COST, HORIZON
#    INTERFACE  BRIDGE        HW   PVID  PRIORITY  PATH-COST  INTERNAL-PATH-COST  HORIZON
0 IH ether2     bridge-VLANs  yes   110  0x80             10                  10  none   

[admin@MikroTik] /interface/mesh>   /interface bridge port print where pvid=120
Flags: I - INACTIVE; H - HW-OFFLOAD
Columns: INTERFACE, BRIDGE, HW, PVID, PRIORITY, PATH-COST, INTERNAL-PATH-COST, HORIZON
#    INTERFACE  BRIDGE        HW   PVID  PRIORITY  PATH-COST  INTERNAL-PATH-COST  HORIZON
1 IH ether3     bridge-VLANs  yes   120  0x80             10                  10  none   
2 IH ether4     bridge-VLANs  yes   120  0x80             10                  10  none  

 
PackElend
Member Candidate
Member Candidate
Posts: 269
Joined: Tue Sep 29, 2020 6:05 pm

Re: [SOLVED] Using Dynamic Variable Names

Fri Apr 01, 2022 11:07 pm

but no clue why
:global result
and
    :local readcomment ( [ :toarray ([/interface ethernet get $Interface]->"comment" ) ]->1 )
    :local readthisfield "vlanid"
are working
but making
:global result
local
    :local readcomment ( [ :toarray ([/interface ethernet get $Interface]->"comment" ) ]->1 )
    :local readthisfield "vlanid"
    :local result 
fails

Moreover, if first global
 [:parse ("global \"$readcomment\";:global result (\$\"$readcomment\"->\"$readthisfield\")")]
is changed to local
 [:parse ("lcoal \"$readcomment\";:global result (\$\"$readcomment\"->\"$readthisfield\")")]
I get
invalid value  for pvid, an integer required
means the comment was not read
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: [SOLVED] Using Dynamic Variable Names

Fri Apr 01, 2022 11:38 pm

Your question is like <<why if I change "3 + 3" to "3 x 3" I have different results?>>

If the variable is not global (or saved inside a file or mikrotik configuration), is not possible to see it inside another running script, as already I say, ":parse" is a separate execution of the script...
And as already wrotten, you must use ":global variable" to inform the separate script than you want to use that global variable.

Local variable exist only inside the "for" cycle, and when you call ":parse", declared or not, is unable to see the variable because is not global.

I understand you want know how the scripts works, but if I say (and demostrate) than 3+3 do 6,
do not ask question aboput because 3x3 do 9... keep the things on how are working...
 
PackElend
Member Candidate
Member Candidate
Posts: 269
Joined: Tue Sep 29, 2020 6:05 pm

Re: [SOLVED] Using Dynamic Variable Names

Sat Apr 09, 2022 3:03 pm

I understand you want know how the scripts works,...
I think I almost have it, see below.
If anyone could answer the remaining question it would be just great :)

[ :parse (" global \"$readcomment\"; :global result ( \$\"$readcomment\" -> \"$readthisfield\" )   ")  ]

  1.  [ ... ] isolated the command? I'm still bit lost how to use (, [ or {. All I can say [ seems to be important when dealing with arrays 
  2.  :parse () anything what is in (" ... ") will converted in string than interpreted as command (parsing). $ are still used to link variable. In our case the variables readcomment and readthisfield
  3.    global \"$readcomment\", declaring a variable named readcomment but as reference to the existing global variable readcomment. It is not a new variable existing within the scope of [ ... ]!
    1.   Is this correct?
    2. It is somehow related to getting somehow access to the variable name (evl /globalname) as below?
      [admin@MikroTik] > :global "vlan_common" {id=100;name="VLAN_COMMON";comment="COMMON SERVICES AND DEVICES / OFFICE"}
      [admin@MikroTik] > :put ($"vlan_common")
      comment=COMMON SERVICES AND DEVICES / OFFICE;id=100;name=VLAN_COMMON
      [admin@MikroTik] > put [:parse ("global \"vlan_common\" ") ]
      (evl /globalname=$vlan_common)
      
  4. ; :global result ( ... ), new command line indicated by ; and new command indicated by :. Whatever is the outcome of ( ... ) is assigned to result.
  5.   \$\"$readcomment\", content of readcomment is parsed into a variable name by prefixing \$. As $ is escaped by \ it is parsed to link to a variable. Assume the content of readcomment is VLAN_USER1, it is parsed as $"VLAN_USER1", so it is linked to the global variable VLAN_USER1. \" is used to put the variable name in quotes as required by the note in Operations with Arrays - Manual:Scripting - MikroTik Wiki.
    1.  How is ensured that it looks for global variable as I readcomment is referenced again but not this one? 
    2.  Is it due to :global?
  6.   \"$readthisfield\", almost the same as above but here, only the array key name is determined what is stored in readthisfield.
  7.  -> is the command to get an array element by key, in our case it would than store the content of the array element stored in "$readthisfield" in the array  $"VLAN_USER1" and store it in $result 
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: [SOLVED] Using Dynamic Variable Names

Sat Apr 09, 2022 11:33 pm

1) If you use put, you obtain the internal equivalent script, if you omit :put, the :parse script is executed
[rex@net] > :put [:parse ":put 777"]  
(eval /putmessage=777)
[rex@net] > [:parse ":put 777"]      
777

2) Parse first convert the string in script, for example:
if readfromthis is "vlan_common" and readthisfield is "name"
this
[:parse ("global \"$readfromthis\";:global result (\$\"$readfromthis\"->\"$readthisfield\")")]
is internally converted first to:
[:parse ("global \"vlan_common\";:global result (\$\"vlan_common\"->\"name\")")]
replacing $readfromthis with "vlan_common" and $readthisfield with "name"
then is converted to internal script language, but for example is converted to:
:global "vlan_common";:global result ($"vlan_common"->"name")

3), 5) and 6) understanding 2) and what are a global variable, the 3), 5 and 6) are useless

4) where is the question?

7) Not, this indicate -> what element you want read or write based on what the script do.
For example on array {id=100;name="VLAN_COMMON";comment="COMMON SERVICES AND DEVICES / OFFICE"}

Read:
:put ($array->"name")
VLAN_COMMON

Write:
:set ($array->"name") "newname"
the array change to {id=100;name="newname";comment="COMMON SERVICES AND DEVICES / OFFICE"}

Who is online

Users browsing this forum: alexantao, Bing [Bot], Google [Bot] and 15 guests