Hi all:
I found that the :find function starts searching from start + 1 (for example, if you want to search from the beginning, start needs to be specified as -1). Is this designed to be like this?
Hi all:
I found that the :find function starts searching from start + 1 (for example, if you want to search from the beginning, start needs to be specified as -1). Is this designed to be like this?
what is the meaning of -1? Usually -1 means “start from end” or “reverse”. But linked documentation is worthless as it describes nothing. MT is not even capable of naming arguments. is just lol. you have a haystack and a needle.
Yes. RouterOS uses 0-based indexes for variables/array/string, so -1 is before the first is logical.
But… totally agree the docs are vague on find’s parameters. Especially since params are different if “find” is an operator on a command (instead of a variable/string).
It’s not important whether routeros uses 0-based index or 1-based index, the key point is that the parameter and return value of the :find function define the index differently, also pay attention to the start parameter of the :pick function. See the example below:
:local str1 "the target string start at position 0"
:local str2 "2Bthe target string start at position 2"
:local targetStr "the"
:local targetIdx
:set targetIdx [:find $str2 $targetStr 1]
:log warn ("targetIdx(search from idx 1) in str2=" . $targetIdx); #->targetIdx(search from idx 1) in str2=2
:log warn [:pick $str2 1 [:len $str2]]; #->Bthe target string start at position 2
:log warn [:pick $str2 2 [:len $str2]]; #->the target string start at position 2
:set targetIdx [:find $str2 $targetStr 2]; #->can't find the target string
:log warn ("targetIdx(search from idx 2) in str2=" . $targetIdx); #->targetIdx(search from idx 2) in str2=
IMO it’s really the docs could be clearer. The example shows a -1, so they give you the clue at least…clarity be better. In formal sense, the is exclusive of itself, so it mean “search-after-this-index” or "start-after=-1:… and next number after -1 is 0, which is the start of the string. Again not in docs, but if you mean the beginning, you can just leave out as it defaults to -1.
But agree this means often using ($n-1) in another [:find] after getting an index if looping, so get the concern. More that :find has work this way a long time, so this limits changes. Flip side is Mikrotik has add a few more higher-level functions (:convert, :serialize, :tolf, :tonsec, etc.) that avoid some need for parsing strings using :find/:pick. But no easy way to “find-and-replace in a string”, without :find/:pick and loops still…
Personally, I’d grip about :grep, which is actually more way more bizarre than :find’s -1, since it takes a “script” (or command)'s output to as what search, retuning a num type with count of matching lines (not a bool) to indicate if match found:
:put [:tobool [:grep "return abcaz" pattern="z.c."]]
# false
:put [:tobool [:grep "return abcasz" pattern="a.c"]]
abcasz
# true
IMO it’s really the docs could be clearer. The example shows a -1, so they give you the clue at least…clarity be better. In formal sense, the is exclusive of itself, so it mean “search-after-this-index” or "start-after=-1:… and next number after -1 is 0, which is the start of the string. Again not in docs, but if you mean the beginning, you can just leave out as it defaults to -1.
I mainly think that this behavior is a bit weird and different from most development languages (I found that many ros scripts on the Internet misused the start parameter of :find function).
And even in ros, the start parameter for :find means “search-after-this-index”, but “get-from-this-index” for :pick.
But agree this means often using ($n-1) in another [:find] after getting an index if looping, so get the concern. More that :find has work this way a long time, so this limits changes. Flip side is Mikrotik has add a few more higher-level functions (:convert, :serialize, :tolf, :tonsec, etc.) that avoid > some > need for parsing strings using :find/:pick. But no easy way to “find-and-replace in a string”, without :find/:pick and loops still…
Yes, this is exactly what I am doing. I hope more and more advanced functions will be available in the future.