Add array element inside for / foreach

I can’t find a way to add an element to a global array inside a for loop.
The array content is being replaced by the last element.

:global interfaces;

:foreach i in=[/interface bridge port find where pvid=80] do={
    :local bport [interface bridge port get number=$i];
    :put ("$bport"->"interface");
    :set $interfaces ($interfaces $bport);
}

:put $interfaces;

Clearly Mikrotik scripting syntax is a pita; honestly, it’s a simple array push function.
I really hope that someone can help me find out the reason why this isn’t working properly.

Close. You need to declare the outer array & use parens+comma to concat values to the array.

:global interfaces [:toarray “”]

:foreach i in=[/interface bridge port find where pvid=80] do={
:local bport [/interface bridge port get number=$i];
:put ($bport->“interface”);
:set $interfaces ($interfaces
,
$bport);
}

Check errors… “$” after :set, useless “;” and $bport is not the interface/port name

Is not clear what is wanted at the end: one array with only all the interfaces name only (where pvid=80), or other?

Better this:

:global interfaces [:toarray ""]

/interface bridge port
:foreach i in=[find where pvid=80] do={
    :set interfaces ($interfaces,[get $i interface])
}

:put $interfaces

Unfortunately, it doesn’t work! Just test it… it should be easy to make something like an array element push I guess.

Well, it's just a random exercise since I'm learning Mikrotik scripting, but the thing is to save every interface data configuration on an array while I'm looping through bridge interfaces with pvid=to some vlan id. Anyway, could you break it down for me, please? I'm a bit confused with the [get $i interface] :slight_smile:

Just that?
:global interfaces [/interface bridge port print detail as-value where pvid=80]

:put $interfaces
:put “$($interfaces->0->“interface”) is on the bridge $($interfaces->0->“bridge”)”
Obviously “put” print results on terminal only if something with pvid=80 exist…

I want to understand how to push an element to an array inside a for / foreach loop!
Besides I can make use of the information generated inside a for loop and make something with it later.
I need to understand the mechanics of a simple element push to an array inside a for loop.

You “push” to an array by concatenating new values, as shown above. There is NO push/pop, only index and re-assignment. But you do have to declare the array when initializing it using [:toarray “”] as the value to create an array type.

More simple example:

:global interfaces [:toarray ""]
:foreach i in=(1,true,"three") do={ 
    :set interfaces ($interfaces,$i) 
}

:put $interfaces
# 1;true;three

:put [:len $interfaces]
# 3

:foreach j in=$interfaces do={ :put $j }
# 1
# true
# three

There some good basic scripting example here: https://wiki.mikrotik.com/wiki/Manual:Scripting_Tips_and_Tricks

I can see now that Mikrotik scripting is the practical result of a collection of wild runs!
I thought that shell scripting was stupid enough but when compared is kinda refreshing…
The syntax is Dantesque and the complexity of possibilities is just outstanding in a bad way.

There must be a valid reason why this doesn’t work, but I can’t understand why since the iface local variable is reassigned in every loop with a new interface array! Perhaps the reason is the array architecture in itself.

:global interfaces [:toarray ""]

:foreach i in=[/interface bridge port find where pvid=80] do={
    :local iface [interface bridge port get number=$i];
    :set interfaces ($interfaces, $iface);
}

:put $interfaces;

@rextended showed this part. The “get” either returns all values, or a specific one (like interface name):

 :local iface [interface bridge port get number=$i] interface;

You can see the difference if you “put” (print) to the console:

:put [/interface bridge port get 0]
:put [/interface bridge port get 0 interface]

It prints interface data OK.
Array assignment doesn’t work, it only saves the last interface.

:global interfaces [:toarray ""]

/interface bridge port
:foreach i in=[find where pvid=10] do={
    :put [get $i];
    :set interfaces ($interfaces,[get $i])
}

:put $interfaces

And it’s perfectly logical, you can’t have two keys with the same name in the same array…


:global example [:toarray ""]

:set example ($example,{"interface"="ether1";"arr1"="yes"})
:set example ($example,{"interface"="ether2";"arr2"="yes"})

:put $example

on results is present both arr1 and arr2, but only one interface, and obviously is the last set.
arr1=yes;arr2=yes;interface=ether2
What you try to do, you want to do wrong.
If you do things randomly and don’t read what I write, that’s your business.
Fix it yourself.

As I said earlier, it’s an array-related architecture thing…
I now understand arrays in Mikrotik scripting do not work as I believed.
Anyways, thank you for pointing that out to me.

What kind of key-value data type supports different value for same key in any programing/script language? How that will be even possible? Key must be unique. :slight_smile:
Create main interfaces array and on each iteration add to it key-valye array for interface data. Then you can access values later by iterating $interfaces array or directly by index $interfaces->$index->“key”, etc…
Like this for eg.:

:global interfaces [:toarray ""]

/interface bridge port
:foreach i in=[find where pvid=10] do={
    :put ([get $i]->"interface")
    :set interfaces ($interfaces, {[get $i]})
}

:put "-----------"

:foreach i in=$interfaces do={
    :put ($i->"interface")
}

Or simply, as already wrote on post #6....

EDIT: Changed pvid

Yes, if there is no need for some other commands in iteration block while populating interfaces array…

For sure, but the user, as example, want just obtain one array with all port interfaces data inside, and whay I have proposed is the fast way without cycles…

Stylistically, @rextended example in #6 is spot on. e.g. why use a foreach+find+get when there is a "/xxx print detail as-value" that get the key-value array for you in one command & then do whatever further operations on that KV array from print...

Thank you all for your contributions, really very informative content!