Community discussions

MikroTik App
 
mark0016
just joined
Topic Author
Posts: 1
Joined: Wed Feb 08, 2023 4:49 pm

find behaves in wierd ways if you pass it something like `domain="$domain"`

Wed Feb 08, 2023 5:37 pm

I couldn't for the life of me figure out what is wrong with my code so I ended up creating this fun little debug script:
/ip dhcp-server network
:put "$domain"
:put [ :typeof "$domain" ]
:put [ :typeof ".lan" ]
:put [ find domain="$domain" ]
:put [ find domain=".lan" ]
:local somethingDifferent "$domain"
:put [ find domain="$somethingDifferent" ]
to which the output I got was:
.lan
str
str
*2;*1
*1
*1
I was convinced some black magic was happening since my variable that I set to the value `.lan` and literally the value `.lan` are giving different results.
I added the final lines naming the variable something else and, bam, it works...

I've checked this with other things as well like
:put [find comment="$comment"]
and it does just return every single ID, even if the variable is empty/undefined. It looks to me like find itself is setting these values internally and then running into some odd behaviour like this.

Honestly I'm not sure what is happening internally and why it works like this, but I really think it shouldn't. The substitution should happen before or as soon as we enter the internal scope of "find". I would expect variable substitution to always be identical to substituting the same value by hand, if I give something an argument I should not have to care about what variable names are used internally by that command/function.

Is this a known limitation, or is it a bug?
 
User avatar
Jotne
Forum Guru
Forum Guru
Posts: 3291
Joined: Sat Dec 24, 2016 11:17 am
Location: Magrathean

Re: find behaves in wierd ways if you pass it something like `domain="$domain"`

Thu Feb 09, 2023 11:29 am

Without telling what you try to do, its hard to help.

To get anything correct out of RouterOS, you need to work with the id of an object.
Here is an example of getting some DHCP network information. (cut/past to terminal)
{

/ip dhcp-server network
:foreach id in=[find] do={
	:put "id=$id domain=$[get $id domain] address=$[get $id address] gateway=$[get $id gateway]"
}
}


-----------------------------------------------------------------------------------------------
Use Splunk> to log/monitor your MikroTik Router(s).--> MikroTik->Splunk :mrgreen:
Backup config to Gmail -->Backup
Block users that tries ut use non open ports -->Block
Last edited by Jotne on Sun Feb 12, 2023 10:13 pm, edited 2 times in total.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: find behaves in wierd ways if you pass it something like `domain="$domain"`

Thu Feb 09, 2023 2:03 pm

@mark0016
>>>Is this a known limitation, or is it a bug?
Yes, is the bug of your limitation.

You do not provide any "script" that give that result.
You omit
:local domain ".lan"
(or similar) at the start
that is only knowed by you, and *1,*2 etc. can be displayed only on your device because only you have your device.


Have you discovered the "hot water"?

Nothing mysterious, as in all languages, you don't have to use the name of a field or a reserved word as the name of a variable...
Logical and clear.
:put [find comment="$comment"]
Translated on human language...
Put (on screen) the results of the find about any item that have on comment the value of it's own comment...

Since the comment is identical as the value of comment...


For example, for search any item that have comment length = 26:
:put [find where ([:len $comment] = 26)]
 
txfz
Frequent Visitor
Frequent Visitor
Posts: 57
Joined: Tue Mar 10, 2020 9:02 am

Re: find behaves in wierd ways if you pass it something like `domain="$domain"`

Thu Feb 09, 2023 3:16 pm

Nothing mysterious, as in all languages, you don't have to use the name of a field or a reserved word as the name of a variable...
Logical and clear.
Can you name another language where parameter names are reserved keywords? Especially only within the context of the function call itself.

The only way this would be logical is if you could do something like
$this->comment
.
 
User avatar
diamuxin
Member
Member
Posts: 319
Joined: Thu Sep 09, 2021 5:46 pm
Location: Alhambra's City

Re: find behaves in wierd ways if you pass it something like `domain="$domain"`

Thu Feb 09, 2023 3:18 pm

Sorry for the off-topic Rex, what about your link to your scripts?
I don't see it in the signature.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: find behaves in wierd ways if you pass it something like `domain="$domain"`

Thu Feb 09, 2023 3:27 pm

Sorry for the off-topic Rex, what about your link to your scripts?
I don't see it in the signature.
All the signature, for abuse, are removed.

You can search "Rextended Fragments" or "Rextended Snippets"
viewtopic.php?t=177551
Last edited by rextended on Thu Feb 09, 2023 3:35 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: find behaves in wierd ways if you pass it something like `domain="$domain"`

Thu Feb 09, 2023 3:34 pm

Can you name another language where parameter names are reserved keywords? Especially only within the context of the function call itself.
It doesn't matter I don't want to argue about other languages, if the example is wrong or not,
but everyone should have common sense, not to call the variables with the usual name of the fields, then there is confusion.

On RouterOS it is like this, and here we are talking about RouterOS, not other languages.

The only way this would be logical is if you could do something like
$this->comment
.
Logical? For what? IS not clear what is it (and the right syntax if is wanted read/set the value is $this->"comment" or $this->$comment)


Is nice to discovery what happen if is used this:
:global x ({})
:set ($x->$x) "test"
:put ($x->$x)
 
txfz
Frequent Visitor
Frequent Visitor
Posts: 57
Joined: Tue Mar 10, 2020 9:02 am

Re: find behaves in wierd ways if you pass it something like `domain="$domain"`

Thu Feb 09, 2023 4:03 pm

Then don't talk about it as something that's a thing in "all languages". The common sense would be to expect it to behave as all other languages and for variables not to get magically overwritten. It is very common to name variables the same as the parameter or field name.
 
User avatar
diamuxin
Member
Member
Posts: 319
Joined: Thu Sep 09, 2021 5:46 pm
Location: Alhambra's City

Re: find behaves in wierd ways if you pass it something like `domain="$domain"`

Thu Feb 09, 2023 4:05 pm

All the signature, for abuse, are removed.
I understand, thank you.

..
 
User avatar
eworm
Forum Guru
Forum Guru
Posts: 1070
Joined: Wed Oct 22, 2014 9:23 am
Location: Oberhausen, Germany
Contact:

Re: find behaves in wierd ways if you pass it something like `domain="$domain"`

Thu Feb 09, 2023 4:08 pm

This is a known problem, though the exact explanation is not known. I asked Mikrotik support and they replied (in Ticket#2019010222000454):
This is how scripting works in RouterOS and we will not fix it.
I have started to use variable names in camel case. So instead of domain=$domain use domain=$Domain, which works as expected.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: find behaves in wierd ways if you pass it something like `domain="$domain"`

Fri Feb 10, 2023 10:49 am

Is WANTED problem, not for create problems, but for use extended syntax on print and find, like my example,
on this way you can do operations on find, for not elaborate twice or more the results.


Some examples:

(on find)
# obtain identity from interface
{
:local int "ether5"
/ip neighbor
:foreach item in=[find where ($interface->0)=$int] do={
    :put [get $item identity]
}
}
Why: "interface" is one array, on this way only the 1st value of the array is parsed

(1st find)
/ip dhcp-server lease
:foreach id in=[find where [:typeof $"active-address"]="ip"] do={
    :local activeMAC    [get $id active-mac-address]
    :local if           "undefined"
    :local outstring    "undefined"
    /interface bridge host
    :local searchresult [find where mac-address=$activeMAC]
    :if ([:len $searchresult] > 0) do={
        :set if [get $searchresult on-interface]
        :set outstring "For bridge host table the $activeMAC is coming from $if"
    } else={
        :set outstring "Not find any result on bridge host table with MAC $activeMAC"
        /ip arp
        :set searchresult [find where mac-address=$activeMAC]
        :if ([:len $searchresult] > 0) do={
            :set if [get ($searchresult->0) interface]
            :set outstring "$outstring, but for ARP table $activeMAC is coming from $if"
        } else={
            :set outstring "$outstring, neither on ARP table."
        }
    }
    :put $outstring
}
Why: Return values only if "active-address" is one IP

Another example (on find)
/ip firewall address-list
add address=79.116.0.0/16 list=checklist
add address=86.127.0.0/16 list=checklist
add address=192.168.0.0/16 list=checklist

:local logIp 86.127.55.66

:if ([:len [find where list=checklist and (($logIp in $address) or ($logIp = $address))]] > 0) do={
    :put "$logIp found inside one, or more, address pool in checklist"
}
 
User avatar
Amm0
Forum Guru
Forum Guru
Posts: 3253
Joined: Sun May 01, 2016 7:12 pm
Location: California

Re: find behaves in wierd ways if you pass it something like `domain="$domain"`

Fri Feb 10, 2023 11:31 am

The way I think about this is that commands are functions, and the standard arguments are "named parameters" to it. And inside a (user-defined) function, the argument names are local variables, so kinda make sense that built-in commands (i.e. function-like) would follow similar scoping rules as user-defined functions.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 11982
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: find behaves in wierd ways if you pass it something like `domain="$domain"`

Fri Feb 10, 2023 11:33 am

[…] commands are functions, and the standard arguments are "named parameters" to it.
And inside a (user-defined) function, the argument names are local variables,
[…] built-in commands (i.e. function-like) would follow similar scoping rules as user-defined functions.
Exactly

Try to paste this on terminal.... ;)
:put [:parse "/ip add find where true"]

parser code

(eval /ip address findwhere=$address;$network;$netmask;$broadcast;$interface;$actual-interface;$invalid;$dynamic;$disabled;$comment;$.id;$.nextid;$.dead;true;0)

Who is online

Users browsing this forum: No registered users and 14 guests