Работа с массивами в скриптах Mikrotik

Пока память свежа, напишу как работать с массивами в RouterOS. Все команды выполняются в терминале обычным копипастом.

Основы

В самом простом случае массив объявляется так:

:global array1 [:toarray "1,2,3"]
:global arrayNum {1;2;3}
:global arrayStr {"n1";"n2";"n3"}

Строковые значения без пробелов почти везде можно не закрывать кавычками. Но для повышения "читабельности" кода и этого маленького "почти", лучше все-таки использовать кавычки.

Количество элементов в массиве вычисляет функция :len:

# эта команда ничего не выведет в терминал
:len $arrayStr
# а вот эта выведет число 3, указывающее на количество элементов в массиве
:put [:len $arrayStr]

Далее будет использоваться команда :put для вывода значения в терминал. Но в скриптах эта команда обычно не используется, разве только для отладки.

Нумерация элементов массива начинается с нуля. Получить элемент из массива по его индексу можно командой :pick:

:put [:pick $arrayStr 1]
# или
:put ($arrayStr->1)
# в обоих случаях результатом будет: n2

Причем единицу можно заменить переменной, например $i. На всякий случай поясню, здесь и далее, текст "[admin@xxx] >" показывает приглашение терминала и его вводить не требуется. Следующие строки показывают результат выполнения команды.

[admin@xxx] > :for i from=0 to=([:len $arrayStr]-1) do={:put ($arrayStr->$i)}
n1
n2
n3

Ну и конечно есть оператор foreach: который перебирает все элементы массива.

[admin@xxx] > :foreach i in=$arrayStr do={:put $i}
n1
n2
n3

Установить значение элемента в массиве, даже если элемента с таким индексом не существует, можно следующим образом:

[admin@xxx] > :set ($arrayStr->4) "n5"

Теперь посмотрим что получилось в массиве. Выведем значения и тип хранимого значения:

[admin@xxx] > :foreach i in=$arrayStr do={:put "$i - type of item:$([:typeof $i])"}
n1 - type of item:str
n2 - type of item:str
n3 - type of item:str
 - type of item:nothing
n5 - type of item:str

Продвинутые методы

В моем скрипте быстрой настройки IPSEC есть такой код(лишь с той разницей, что там используется локальная переменная) объявляющий структуру предприятия:

  :global structNET {
    "Company Z: OfficeHQ"={ip=23.5.230.7 ; lan=192.168.11.0/24 ; rootnode=true} ;
    "Company Z: Office2"={ip=189.2.134.7 ; lan=192.168.12.0/24} ;
    "Company Z: Office3"={ip=95.36.71.7 ; lan=192.168.13.0/24} ;
    "Company Z: Office4"={ip=154.4.96.7 ; lan=192.168.14.0/24 ; initiator=true ; rootnode=true} ;
  }

Обращаться к элементам такого массива можно следующим образом:

[admin@xxx] > :put ($structNET->"Company Z: Office4")
initiator=true;ip=154.4.96.7;lan=192.168.14.0/24;rootnode=true

[admin@xxx] > :put ($structNET->"Company Z: Office4"->"ip")
154.4.96.7

Естественно, что вместо литералов могут использоваться переменные, как было показано в примере выше, где 1 заменялась на $i. А вот конструкция с :pick , может преподнести сюрприз:

[admin@xxx] > :put [:pick $structNET 0]
ip=189.2.134.7;lan=192.168.12.0/24

Подозреваю, это связано с сортировкой именованных элементов массива. И вывод foreach следующего примера это доказывает.

Перебор всех элементов при помощи :foreach:

[admin@xxx] > :foreach office,data in=$structNET do={ :put $office; :put $data;}
Company Z: Office2
ip=189.2.134.7;lan=192.168.12.0/24
Company Z: Office3
ip=95.36.71.7;lan=192.168.13.0/24
Company Z: Office4
initiator=true;ip=154.4.96.7;lan=192.168.14.0/24;rootnode=true
Company Z: OfficeHQ
ip=23.5.230.7;lan=192.168.11.0/24;rootnode=true