Вот скрипт, который оказался для меня полезным, надеюсь, и другим он пригодится. Я уже несколько лет пользуюсь Mikrotik и заметил, что часто использую один и тот же код. Скрипты Mikrotik CMD не поддерживают функции, которые можно вызывать из других скриптов, поэтому я решил придумать простой способ это обойти. Публикую здесь, чтобы получить ваши комментарии, предложения и отзывы по этому коду. Если все недочеты будут устранены, надеюсь, что и другие смогут добавить свои функции. Важно: Lua умеет работать с функциями внутри скриптов, но она не реализована в RouterOS версии v2.x, v3.30 и v4.5. Также можно использовать несколько скриптов с глобальными переменными для передачи данных между ними, но это требует, чтобы никакой другой скрипт не использовал те же глобальные переменные. Благодаря «внедрению» глобальных переменных в функции, функции становятся более гибкими и уменьшается вероятность конфликтов глобальных переменных. Итак, сам скрипт:
# Имя скрипта: Functions
# Библиотека функций
# Помните: символы '$' (доллар), '"' (двойные кавычки) и '\' (обратный слеш) внутри функций должны экранироваться обратным слешем '\'
# Входной массив функции передается из вызывающего скрипта так:
# строка: ":local input \"<input1,input2,...>\"; "
# результат команды: ":local input [/path/to/command get <item property>];"
# Выходной массив функции сохраняется в локальной переменной $output
# Функции всегда должны заканчиваться ; (точкой с запятой) — так их удобнее вызывать из других скриптов
# Пример вызова функции MyFunc с входом "1,2,3,4" и сохранением результата в глобальную переменную MyOutput
# В вызывающем скрипте:
# Код
# /system script run "Functions"
# :global MyFunc
#
# :global MyOutput ""
# :local runFunc [:parse (":global MyOutput;" . \
# ":local input \"1,2,3,4\";" . \
# $MyFunc . \
# ":set MyOutput \$output")
# ]
# $runFunc
# Конец кода
# Глобальная переменная $MyOutput теперь содержит массив с результатами функции
# Для вывода результата:
# :put [:pick $MyOutput 0]
# :put [:pick $MyOutput 1]
# :put [:pick $MyOutput 2]
# :put [:pick $MyOutput ...]
# Функции
#------------
# RandomNumGen: Генерирует достаточно случайное число на основе даты, времени, свободной памяти и загрузки CPU
# Входной массив: отсутствует
# Выходной массив:
# 0 = сгенерированное число
:global RandomNumGen ":local output \"\"
:set output (\$output . [:pick [/system clock get date] 7 11])
:set output (\$output . [:pick [/system clock get date] 4 6])
:set output (\$output . [:pick [/system clock get time] 0 2])
:set output (\$output . [:pick [/system clock get time] 3 5])
:set output (\$output . [:pick [/system clock get time] 6 8])
:set output (\$output . [/system resource get free-memory])
:set output (\$output . [/system resource get cpu-load])
:set output [:tonum \$output]
:set output [:toarray \$output];"
# DateToNum: Преобразует дату в формате "mmm/dd/yyyy" в числовой формат "yyyymmdd"
# Входной массив:
# 0 = строка даты "mmm/dd/yyyy"
# Выходной массив:
# 0 = числовая дата yyyymmdd
:global DateToNum " :local output \"\"
:set input [:toarray \$input]
:if ([:len \$input] > 0) do={
:local input1 [:tostr [:pick \$input 0]]
:local months [:toarray \"jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec\"]
:local mon 0
:for x from=0 to=([:len \$months] - 1) do={
:if ([:tostr [:pick \$months \$x]] = [:tostr [:pick \$input1 0 3]]) do={
:if (\$x < 9) do={ :set mon (\"0\" . (\$x + 1)) } else={ :set mon (\$x + 1) } } }
:set output ([:pick \$input1 7 11] . \$mon . [:pick \$input1 4 6])
:set output [:tonum \$output]
:set output [:toarray \$output]
};"
# TimeToNum: Убирает двоеточия из строки времени "hh:mm:ss" -> "hhmmss"
# Входной массив:
# 0 = строка времени "hh:mm:ss"
# Выходной массив:
# 0 = числовое время hhmmss
:global TimeToNum " :local output \"\"
:set input [:toarray \$input]
:if ([:len \$input] > 0) do={
:local input1 [:tostr [:pick \$input 0]]
:for x from=0 to=([:len \$input1] - 1) do={
:if ([:tostr [:pick \$input1 \$x (\$x + 1)]] != \":\") do={
:set output (\$output . [:tostr [:pick \$input1 \$x (\$x + 1)]]) } }
:set output [:tonum \$output]
:set output [:toarray \$output]
};"
# RegExFind: Ищет точное соответствие регулярному выражению в строке
# Входной массив:
# 0 = строка для поиска
# 1 = шаблон регулярного выражения
# Выходной массив:
# 0 = индекс начала совпадения (-1, если не найдено)
# 1 = индекс конца совпадения (-1, если не найдено)
:global RegExFind " :local output \"\"
:set input [:toarray \$input]
:if ([:len \$input] > 1) do={
:local input1 [:tostr [:pick \$input 0]]
:local input2 [:tostr [:pick \$input 1]]
:for x from=0 to=([:len \$input1] - 1) do={
:if ([:pick \$input1 \$x [:len \$input1]] ~ (\"^\" . \$input2)) do={
:for y from=\$x to=([:len \$input1] - 1) do={
:if ([:pick \$input1 \$x (\$y + 1)] ~ (\$input2 . \"\\\$\")) do={
:set output (\$x . \",\" . \$y) } } } }
:if ([:len \$output] = 0) do={ :set output \"-1,-1\" }
:set output [:toarray \$output]
};"
# -----------------
# Конец библиотеки функций
# Скрипт-пример использования функций # Имя скрипта: DemoFunctions
# Демонстрация библиотеки функций
# Импорт скрипта Functions и используемых функций
/system script run "Functions"
:global RandomNumGen
:global DateToNum
:global TimeToNum
# Демонстрация RandomNumGen
:global DemoRandomNum 0
:local runFunc [:parse (":global DemoRandomNum;" . \
$RandomNumGen . \
":set DemoRandomNum \$output")
]
$runFunc
:put ("Случайное число: " . [:pick $DemoRandomNum 0])
# Демонстрация DateToNum
:global DemoDate 0
:local runFunc [:parse (":global DemoDate;" . \
":local input [/system clock get date]; " . \
$DateToNum . \
":set DemoDate \$output")
]
$runFunc
:put ("Дата в числовом формате: " . [:pick $DemoDate 0])
# Демонстрация TimeToNum
:global DemoTime 0
:local runFunc [:parse (":global DemoTime;" . \
":local input [/system clock get time]; " . \
$TimeToNum . \
":set DemoTime \$output")
]
$runFunc
:put ("Время в числовом формате: " . [:pick $DemoTime 0])
Снова, пожалуйста, оставляйте отзывы и предложения.
# Имя скрипта: Functions
# Библиотека функций
# Помните: символы '$' (доллар), '"' (двойные кавычки) и '\' (обратный слеш) внутри функций должны экранироваться обратным слешем '\'
# Входной массив функции передается из вызывающего скрипта так:
# строка: ":local input \"<input1,input2,...>\"; "
# результат команды: ":local input [/path/to/command get <item property>];"
# Выходной массив функции сохраняется в локальной переменной $output
# Функции всегда должны заканчиваться ; (точкой с запятой) — так их удобнее вызывать из других скриптов
# Пример вызова функции MyFunc с входом "1,2,3,4" и сохранением результата в глобальную переменную MyOutput
# В вызывающем скрипте:
# Код
# /system script run "Functions"
# :global MyFunc
#
# :global MyOutput ""
# :local runFunc [:parse (":global MyOutput;" . \
# ":local input \"1,2,3,4\";" . \
# $MyFunc . \
# ":set MyOutput \$output")
# ]
# $runFunc
# Конец кода
# Глобальная переменная $MyOutput теперь содержит массив с результатами функции
# Для вывода результата:
# :put [:pick $MyOutput 0]
# :put [:pick $MyOutput 1]
# :put [:pick $MyOutput 2]
# :put [:pick $MyOutput ...]
# Функции
#------------
# RandomNumGen: Генерирует достаточно случайное число на основе даты, времени, свободной памяти и загрузки CPU
# Входной массив: отсутствует
# Выходной массив:
# 0 = сгенерированное число
:global RandomNumGen ":local output \"\"
:set output (\$output . [:pick [/system clock get date] 7 11])
:set output (\$output . [:pick [/system clock get date] 4 6])
:set output (\$output . [:pick [/system clock get time] 0 2])
:set output (\$output . [:pick [/system clock get time] 3 5])
:set output (\$output . [:pick [/system clock get time] 6 8])
:set output (\$output . [/system resource get free-memory])
:set output (\$output . [/system resource get cpu-load])
:set output [:tonum \$output]
:set output [:toarray \$output];"
# DateToNum: Преобразует дату в формате "mmm/dd/yyyy" в числовой формат "yyyymmdd"
# Входной массив:
# 0 = строка даты "mmm/dd/yyyy"
# Выходной массив:
# 0 = числовая дата yyyymmdd
:global DateToNum " :local output \"\"
:set input [:toarray \$input]
:if ([:len \$input] > 0) do={
:local input1 [:tostr [:pick \$input 0]]
:local months [:toarray \"jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec\"]
:local mon 0
:for x from=0 to=([:len \$months] - 1) do={
:if ([:tostr [:pick \$months \$x]] = [:tostr [:pick \$input1 0 3]]) do={
:if (\$x < 9) do={ :set mon (\"0\" . (\$x + 1)) } else={ :set mon (\$x + 1) } } }
:set output ([:pick \$input1 7 11] . \$mon . [:pick \$input1 4 6])
:set output [:tonum \$output]
:set output [:toarray \$output]
};"
# TimeToNum: Убирает двоеточия из строки времени "hh:mm:ss" -> "hhmmss"
# Входной массив:
# 0 = строка времени "hh:mm:ss"
# Выходной массив:
# 0 = числовое время hhmmss
:global TimeToNum " :local output \"\"
:set input [:toarray \$input]
:if ([:len \$input] > 0) do={
:local input1 [:tostr [:pick \$input 0]]
:for x from=0 to=([:len \$input1] - 1) do={
:if ([:tostr [:pick \$input1 \$x (\$x + 1)]] != \":\") do={
:set output (\$output . [:tostr [:pick \$input1 \$x (\$x + 1)]]) } }
:set output [:tonum \$output]
:set output [:toarray \$output]
};"
# RegExFind: Ищет точное соответствие регулярному выражению в строке
# Входной массив:
# 0 = строка для поиска
# 1 = шаблон регулярного выражения
# Выходной массив:
# 0 = индекс начала совпадения (-1, если не найдено)
# 1 = индекс конца совпадения (-1, если не найдено)
:global RegExFind " :local output \"\"
:set input [:toarray \$input]
:if ([:len \$input] > 1) do={
:local input1 [:tostr [:pick \$input 0]]
:local input2 [:tostr [:pick \$input 1]]
:for x from=0 to=([:len \$input1] - 1) do={
:if ([:pick \$input1 \$x [:len \$input1]] ~ (\"^\" . \$input2)) do={
:for y from=\$x to=([:len \$input1] - 1) do={
:if ([:pick \$input1 \$x (\$y + 1)] ~ (\$input2 . \"\\\$\")) do={
:set output (\$x . \",\" . \$y) } } } }
:if ([:len \$output] = 0) do={ :set output \"-1,-1\" }
:set output [:toarray \$output]
};"
# -----------------
# Конец библиотеки функций
# Скрипт-пример использования функций # Имя скрипта: DemoFunctions
# Демонстрация библиотеки функций
# Импорт скрипта Functions и используемых функций
/system script run "Functions"
:global RandomNumGen
:global DateToNum
:global TimeToNum
# Демонстрация RandomNumGen
:global DemoRandomNum 0
:local runFunc [:parse (":global DemoRandomNum;" . \
$RandomNumGen . \
":set DemoRandomNum \$output")
]
$runFunc
:put ("Случайное число: " . [:pick $DemoRandomNum 0])
# Демонстрация DateToNum
:global DemoDate 0
:local runFunc [:parse (":global DemoDate;" . \
":local input [/system clock get date]; " . \
$DateToNum . \
":set DemoDate \$output")
]
$runFunc
:put ("Дата в числовом формате: " . [:pick $DemoDate 0])
# Демонстрация TimeToNum
:global DemoTime 0
:local runFunc [:parse (":global DemoTime;" . \
":local input [/system clock get time]; " . \
$TimeToNum . \
":set DemoTime \$output")
]
$runFunc
:put ("Время в числовом формате: " . [:pick $DemoTime 0])
Снова, пожалуйста, оставляйте отзывы и предложения.
