Community discussions

MikroTik App
 
dfdf
newbie
Topic Author
Posts: 36
Joined: Wed Dec 08, 2021 3:51 pm

Graphs download script

Sun Dec 24, 2023 2:34 am

This script is intended to download graphing results produced by router (Tools-Graphing).
It downloads results to a writable location (for ex. - attached USB drive) from either local (itself) or remote mikrotik.
HTML files are than rebased to allow local navigation. Feel free to test/discuss/etc.
Syntax styling will not be discussed :)
# Backup graphing data
# Copyright 2023 by Dmitry F. https://t.me/NoOneNoOne
# GNU General Public License version 3
# inspired by:
# https://wiki.mikrotik.com/wiki/Backup_graphing_data
# https://forum.mikrotik.com/viewtopic.php?t=39166
# https://router-os.github.io/Backup-graphing-data.html

:local "graphAddress" "192.168.88.1";
:local "graphPort" "80";
:local "baseDST" "usb1-part1/.log/graphs_";

:local "indexHTML" "index.html";
:local "graphImages" {"daily.gif"; "weekly.gif" ; "monthly.gif" ; "yearly.gif"};
:local "rootFiles" {""; "favicon.png"; "favicon.svg"; "graph.css"};

# functions
:local "urlEncode" do={
 :local "input" [:tostr $1];

 :if ([:len $"input"]=0) do={ :return ""; }

 :local "ret" "";
 :local "chars" "\n\r !\"#\$%&'()*+,:;<=>\?@[\\]^`{|}~";
 :local "subs" {
  "%0A"; "%0D"; "%20"; "%21"; "%22"; "%23"; "%24"; "%25"; "%26"; "%27";
  "%28"; "%29"; "%2A"; "%2B"; "%2C"; "%3A"; "%3B"; "%3C"; "%3D"; "%3E"; "%3F";
  "%40"; "%5B"; "%5C"; "%5D"; "%5E"; "%60"; "%7B"; "%7C"; "%7D"; "%7E" 
 };

 :for "i" from=0 to=([:len $"input"]-1) do={
  :local "char" [:pick $"input" $"i"];
  :local "replace" [:find $"chars" $"char"];

  :if ($"replace">=0) do={
   :set $"char" ($"subs"->$"replace");
  }
  :set $"ret" ($"ret".$"char");
 }

 :return $"ret";
}

:local "rebaseHTML" do={
 :local "ok" (true);
 :local "content" "";
 :local "newContent" "";
 :local "contentLen" 0;
 :local "lineEnd" 0;
 :local "line" "";
 :local "lastEnd" 0; 
 :local "result" [:toarray ""];
 :local "pos" 0;
 :local "matched" (false);
 :local "depth" "";
 :local "resourcesURLs" [:toarray ""];

 :if ([:tostr $"url"]="" or [:tostr $"dstFile"]="") do={ :return []; }
 :if ([:tostr $"indexHTML"]="") do={ :set $"indexHTML" "index.html"; }
 :for "i" from=1 to=(0+[:tonum $"level"]) step=1 do={
  :set $"depth" ($"depth"."../");
 }

 :local "regExArr" {
# <p><a href="/graphs/">Main page</a>
  {"re"=".*<a\\s+href=\"\\/graphs\\/\">.*"; 
   "todo"={
    {"find"="href=\"/graphs/"; "replace"=("href=\"".$"depth")};
    {"find"="/\">"; "insert"=("/".$"indexHTML")}
   }
  };
  {"re"=".*<a\\s+href='\\/graphs\\/'>.*"; 
   "todo"={
    {"find"="href='/graphs/"; "replace"=("href='".$"depth")};
    {"find"="/'>"; "insert"=("/".$"indexHTML")}
   }
  };
  {"re"=".*<a\\s+href=\\/graphs\\/>.*"; 
   "todo"={
    {"find"="href=/graphs/"; "replace"=("href=".$"depth")};
    {"find"="/>"; "insert"=("/".$"indexHTML")}
   }
  };

# <li><a href='cpu/'>CPU usage</a>   
  {"re"=".*<a\\s+href=\".*\\/\">.*"; 
   "todo"={
    {"find"="href=\"/"; "replace"=("href=\"".$"depth")};
    {"find"="/\">"; "insert"=("/".$"indexHTML")}
   }
  };
  {"re"=".*<a\\s+href='.*\\/'>.*"; 
   "todo"={
    {"find"="href='/"; "replace"=("href='".$"depth")}; 
    {"find"="/'>"; "insert"=("/".$"indexHTML")}
   }
  };
  {"re"=".*<a\\s+href=.*\\/>.*"; 
   "todo"={
    {"find"="href=/"; "replace"=("href=".$"depth")};
    {"find"="/>"; "insert"=("/".$"indexHTML")}
   }
  };

# <link rel=icon href=/favicon.png>
# <link rel=stylesheet href=/graph.css>
  {"re"=".*<link\\s+.*\\s+href=\\/.*>.*";
   "todo"={
    {"find"="href=/"; "replace"=("href=".$"depth")}
   }
  };
  {"re"=".*<link\\s+.*\\s+href='\\/.*'>.*";
   "todo"={
    {"find"="href='/"; "replace"=("href='".$"depth")}
   }
  }
 }

 :local "regExArrMainPage" {
# <li><a href='/graphs/iface/bridge/'>bridge</a>
  {"re"="<li><a\\s+href=\"\\/graphs\\/(iface|queue)\\/.*\\/\">.*</a>"; 
   "todo"={
    {"find"="href='/"; "replace"=("href='".$"depth")}; 
    {"find"="/\">"; "insert"=("/".$"indexHTML")}; 
    {"find"="\">"; "margin"="<"; "types"={"/iface/";"/queue/"}}
   }
  };
  
  {"re"="<li><a\\s+href='\\/graphs\\/(iface|queue)\\/.*\\/'>.*</a>"; 
   "todo"={
    {"find"="href='/"; "replace"=("href='".$"depth")}; 
    {"find"="/'>"; "insert"=("/".$"indexHTML")}; 
    {"find"="'>"; "margin"="<"; "types"={"/iface/";"/queue/"}}
   }
  };

  {"re"="<li><a\\s+href=\\/graphs\\/(iface|queue)\\/.*\\/>.*</a>"; 
   "todo"={
    {"find"="href=/"; "replace"=("href=".$"depth")}; 
    {"find"="/>"; "insert"=("/".$"indexHTML")}; 
    {"find"="'>"; "margin"="<"; "types"={"/iface/";"/queue/"}}
   }
  }
 }
 
 :if ((0+[:tonum $"level"])=0) do={
  :set $"regExArr" ($"regExArrMainPage", $"regExArr");
 }
 
 :local "fetchTime" [:time {
  :do { 
   :set $"result" [/tool fetch url=$"url" mode=http output=user as-value];
  } on-error={ :set $"ok" (false); }
 }];
 
 :put ("      status: ". $"result"->"status");
 :put ("       total: ". $"result"->"downloaded"."KiB");
 :put ("    duration: ". $"fetchTime"); 
 :put ""; 

 :if ($"ok" and $"result"->"status"="finished") do={
  :set $"content" ($"result"->"data");
  :set $"contentLen" [:len $"content"];
  :do {
   :set $"lineEnd" [:find $"content" "\n" $"lastEnd"];
   :set $"line" [:pick $"content" $"lastEnd" $"lineEnd"];
   :set $"lastEnd" ($"lineEnd"+1);
   # :put ($"line"." ---> ".($"line"~$"regEx"));
   :set $"matched" (false);
   
   :foreach "regEx" in=$"regExArr" do={
    :if (!$"matched" and $"line"~($"regEx"->"re")) do={
     :set $"matched" (true);
     :foreach "todo" in=($"regEx"->"todo") do={
      :set $"pos" [:find $"line" ($"todo"->"find")];
      :if ($"pos">0) do={
       :if ([:len ($"todo"->"insert")]>0) do={
        :set $"line" ([:pick $"line" 0 $"pos"].($"todo"->"insert").[:pick $"line" ($"pos"+1) [:len $"line"]]);
       } 
       :if ([:len ($"todo"->"replace")]>0) do={
        :set $"line" ([:pick $"line" 0 $"pos"].($"todo"->"replace").[:pick $"line" ($"pos"+[:len ($"todo"->"find")]) [:len $"line"]]);
       }
       :if ([:len ($"todo"->"types")]>0) do={
        :local "type" "";
        :foreach "t" in=($"todo"->"types") do={
         :if ($"type"="" and [:find $"line" $"t"]>0) do={ :set $"type" $"t"; }
        }
        :set $"resourcesURLs" ($"resourcesURLs", {{"type"=$"type"; "name"=([:pick $"line" ($"pos"+[:len ($"todo"->"find")]) [:find $"line" ($"todo"->"margin") ($"pos"+[:len ($"todo"->"find")])]])}});
       }
      }
     }
    }
   }
   # :put $"line";
   :set $"newContent" ($"newContent".$"line"."\r");
  } while ($"lastEnd"<$"contentLen");
  :do {
   /file {
    :if ([:len [find name=$"dstFile"]]>0) do={
     set $"dstFile" contents=$"newContent";
    } else={
     add name=$"dstFile" contents=$"newContent";
    }
   }
  } on-error={ :set $"ok" (false); };
 }
  
 :if (!$"ok") do={
  :set $"resourcesURLs" (false);
 }
 
 :return $"resourcesURLs";
}

# main script starts here
:local "baseURL" ("http://" . $"graphAddress".":".$"graphPort"."/");

:local "curDate" [/system clock get date];
:local "curYear" [:pick $"curDate" 0 4];
:local "curMonth"  [:pick $"curDate" 5 7];
:local "curDay" [:pick $"curDate" 8 10];
:local "systemName" [/system identity get name];
:local "outFolder" ($"systemName"."_".$"curYear"."-".$"curMonth"."-".$"curDay"."/");

:local "graphPath";
:local "graphPathDST";
:local "resourcesURLs" [:toarray ""];
:local "ok" (true);

# Fetch main graphs page and build resources list based on main page URLs
:put "==> Fetching main page graphs... <==";
:set $"graphPathDST" ($"baseDST".$"outFolder");
/file remove [find name=$"graphPathDST"];
:foreach "file" in=$"rootFiles" do={
 :if ($"ok") do={
  :if ($"file"="") do={
   :put (" ".$"baseURL"."graphs/");
   :set $"resourcesURLs" [$"rebaseHTML" url=($"baseURL"."graphs/") dstFile=($"graphPathDST".$"indexHTML") level=0];
   :set $"ok" ($"resourcesURLs"!=false);
  } else={
   :put (" ".$"baseURL".$"file");
   :do {
    /tool fetch url=($"baseURL".[$"urlEncode" $"file"]) mode=http dst-path=($"graphPathDST".$"file") output=file;
   } on-error={ :set $"ok" (false); };
  }
 }
}

:if (!$"ok") do={
 /file remove [find name=($"baseDST".$"outFolder")];
 :error "Graphs download error occured.";
}

# main resources (cpu/ram/hdd) graphs
:put "==> Fetching resources graphs... <==";
:foreach "resource" in={"cpu/"; "ram/"; "hdd/"} do={
 :if ($"ok") do={
  :set $"graphPath" ("graphs/".$"resource");
  :set $"graphPathDST" ($"baseDST".$"outFolder".$"resource");
  :put (" ".$"baseURL".$"graphPath");
  :set $"ok" ([$"rebaseHTML" url=($"baseURL".[$"urlEncode" $"graphPath"]) dstFile=($"graphPathDST".$"indexHTML") level=1]!=false);
  :if ($"ok") do={
   :foreach "image" in=$"graphImages" do={
    :if ($"ok") do={
     :put (" ".$"baseURL".$"graphPath".$"image");
     :do {
      /tool fetch mode=http url=($"baseURL".[$"urlEncode" ($"graphPath".$"image")]) dst-path=($"graphPathDST".$"image") output=file;
     } on-error={ :set $"ok" (false); };
    }
   } 
  }
 }
}

:if (!$"ok") do={
 /file remove [find name=($"baseDST".$"outFolder")];
 :error "Graphs download error occured.";
}

# other resources (interface/queue) graphs
:put "==> Fetching interfaces/queues graphs... <==";
:foreach "resource" in=$"resourcesURLs" do={
 :if ($"ok") do={
  :put (" resource (".$"resource"->"type"."): ".$"resource"->"name");
  :set $"graphPath" ("graphs".$"resource"->"type".$"resource"->"name"."/")
  :set $"graphPathDST" ($"baseDST".$"outFolder"."graphs".$"resource"->"type".$"resource"->"name"."/");
  :put (" ".$"baseURL".$"graphPath");
  :set $"ok" ([$"rebaseHTML" url=($"baseURL".[$"urlEncode" $"graphPath"]) dstFile=($"graphPathDST".$"indexHTML") level=3]!=false);
  :if ($"ok") do={
   :foreach "image" in=$"graphImages" do={
    :put (" ".$"baseURL".$"graphPath".$"image");
    :do {
     /tool fetch mode=http url=($"baseURL".[$"urlEncode" ($"graphPath".$"image")]) dst-path=($"graphPathDST".$"image") output=file;
    } on-error={ :set $"ok" (false); };
   }
  }
 }
}

:if (!$"ok") do={
 /file remove [find name=($"baseDST".$"outFolder")];
 :error "Graphs download error occured.";
}

:put "==> Done. <==";

You do not have the required permissions to view the files attached to this post.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12032
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Graphs download script

Sun Dec 24, 2023 12:08 pm

Too much useless frills like
:local "subs" {
  "%0A"; "%0D"; "%20"; "%21"; "%22"; "%23"; "%24"; "%25"; "%26"; "%27";
  "%28"; "%29"; "%2A"; "%2B"; "%2C"; "%3A"; "%3B"; "%3C"; "%3D"; "%3E"; "%3F";
  "%40"; "%5B"; "%5C"; "%5D"; "%5E"; "%60"; "%7B"; "%7C"; "%7D"; "%7E" 
};
 
:local "char" [:pick $"input" $"i"];
:local "replace" [:find $"chars" $"char"];
  
:put (" ".$"baseURL".$"graphPath");

must be
:local subs [:toarray "%0A,%0D,%20,%21,%22,%23,%24,%25,%26,%27,%28,%29,%2A,%2B,%2C,\
                       %3A,%3B,%3C,%3D,%3E,%3F,%40,%5B,%5C,%5D,%5E,%60,%7B,%7C,%7D,%7E"]
 
:local char    [:pick $input $i]
:local replace [:find $chars $char]

:put " $baseURL$graphPath"
 
dfdf
newbie
Topic Author
Posts: 36
Joined: Wed Dec 08, 2021 3:51 pm

Re: Graphs download script

Sun Dec 24, 2023 1:43 pm

must be
no, just "can be". It's a point of style and choice, no more.
 
optio
Long time Member
Long time Member
Posts: 696
Joined: Mon Dec 26, 2022 2:57 pm

Re: Graphs download script

Sun Dec 24, 2023 2:21 pm

Point is to reduce (minimize) script size by number of characters but still to be cognitive simple to read (not obusficaterd), for eg. using quotation for variable names is unnecessary where is not needed and that generates extra characters in script and to some less readable code since string values are defined in same way. Terminating commands by ; at end of line is also unnecessary extra character since commands are terminated with new line character - from doc: "The end of the command line is represented by the token “;” or NEWLINE. Sometimes “;” or NEWLINE is not required to end the command line."
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12032
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Graphs download script

Sun Dec 24, 2023 9:07 pm

must be
no, just "can be". It's a point of style and choice, no more.
2+2 can also be written ((1+1)+(1+1)), or even worse.
There's no limit to how badly you can write a script that still gives the right result in the end,
but surely if you write like shit, then only you understand, and it's an example of shit for others too.


Syntax styling will not be discussed :)
false assumption

And then I was also not very polemical, because with
:set $"ret" ($"ret".$"char");

# correct
:set ret "$ret$char"

and with
do={ :return []; }
you did a really shitty job.

Don't you know that after :set you shouldn't put $???
That's really a error, it's not a style.
But obviously you know more, with your style, so go ahead as you want, nothing changes anyway.
 
dfdf
newbie
Topic Author
Posts: 36
Joined: Wed Dec 08, 2021 3:51 pm

Re: Graphs download script

Sun Dec 24, 2023 10:51 pm

you did a really shitty job
and you do really a shitty comments, as usual, nothing changes, but you're not a king of hill here. just a man who wrote a bunch of scripts, no more.
 
dfdf
newbie
Topic Author
Posts: 36
Joined: Wed Dec 08, 2021 3:51 pm

Re: Graphs download script

Sun Dec 24, 2023 10:57 pm

Don't you know that after :set you shouldn't put $???
thanx, I'll correct this, but I do remember I've seen this marked as a mistake without $, maybe long ago or in another case.

UPD: no, I will not change anything, found the reason to use my variant with set:
:set t "test";
:put "t is: $t";
code above bails out with "syntax error on line 1"
:set $t "test";
:put "t is: $t";
code above works as expected - prints "t is: test".

This allows omitting :local declaration, when there're a lot of vars - it's a common mistake, while empty var is more evil than this kind of "error".
Because ROS "language" is a nightmare, so again - this is a better approach for me. you can begin another holy-war about "must use :local", you have time to preach when not even asked for, a-ha
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12032
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Graphs download script

Mon Dec 25, 2023 11:26 am

Poor thing.

so go ahead as you want, nothing changes anyway.
 
optio
Long time Member
Long time Member
Posts: 696
Joined: Mon Dec 26, 2022 2:57 pm

Re: Graphs download script

Mon Dec 25, 2023 1:14 pm

This allows omitting :local declaration, when there're a lot of vars - it's a common mistake, while empty var is more evil than this kind of "error".
Why not use declaration with value like is documented -
:local t "test"
? No need for empty declarations and set value after. Using set with $ without declaration is just something that works but not documented and maybe on intrepreter changes in some future ROS version will stop working without notice and you will need to update scripts. Better stick to documented syntax to ensure that future version will support it.
 
dfdf
newbie
Topic Author
Posts: 36
Joined: Wed Dec 08, 2021 3:51 pm

Re: Graphs download script

Mon Dec 25, 2023 8:50 pm

will stop working without notice
Correct. No guarantee. As usual with ROS (see tons of posts on this forum about bugs not being fixed for ages, as well as new features brakes old scripts). So a matter of a lottery - I had to rewrite all my scripts after 7.10 release - rextended, so being totally non-polite, was kind to share this info before final release of 7.10 . Than why should I think about a mystery "compatibility" when Mikrotik has no obligations on this? Moreover, :set $var "val" works fine in ROS 6.4x (at least) till 7.x. Again: in such an "environment" chances you'll have to rewrite your scripts are high regardless of follow or not documented rules. And moreover - many things can be done using only undocumented features.

viewtopic.php?p=993844
viewtopic.php?p=976091
viewtopic.php?p=1039561

Yet another example of undocumented useful feature (writing C-style if assignment):
[admin@] > :put ([:if (true) do={ (true) } else={ (false) }]->1);           
true
[admin@] > :put ([:if (false) do={ (true) } else={ (false) }]->1);               
false
[admin@] > :put [:typeof ([:if (false) do={ (true) } else={ (false) }]->1)];
bool
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12032
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Graphs download script

Mon Dec 25, 2023 10:12 pm

Without a practical example, it is completely useless to write 1+1+1+1+1+1+1+1 instead of 1*7
[admin@] > :put (true)
true
[admin@] > :put (false)
false
[admin@] > :put [:typeof (false)]
bool


But if the final goal is everytime return boolean true or false:

just some examples code

[admin@] > :put (!![:tobool [:nothing]])
false
[admin@] > :put (!![:tobool 0])
false
[admin@] > :put (!![:tobool 200])
true
[admin@] > :put (!![:tobool -11])
true
[admin@] > :put (!![:tobool [:find ""]]) ; # [:find ""] is "nil"
false
[admin@] > :put (!![:tobool ""]) ; # a string, empty or not, is everytime false
false
[admin@] > :put (!![:tobool "true"]) ; # false because true is a string
false
[admin@] > :put (!![:tobool true])
true
[admin@] > :put (!![:tobool [:toarray ""]]) ; # empty array
false        
[admin@] > :put (!![:tobool [:toarray "a"]]) ; # array with at least one element inside
true
 
dfdf
newbie
Topic Author
Posts: 36
Joined: Wed Dec 08, 2021 3:51 pm

Re: Graphs download script

Mon Dec 25, 2023 11:27 pm

...Without a practical example...
[admin@] > :set $"var" ([:if ($"var1"=1) do={ ("one") } else={ ("not one") }]->1); put $"var"
not one
[admin@] > :local "func" do={ :put $1}; [$"func" ([:if ($"var"=1) do={ ("one") } else={ ("not one") }]->1)]     
not one
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12032
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Graphs download script

Tue Dec 26, 2023 6:18 am

do the same and is more readable without array frills & Co.

example code

{
:local func do={:if ($1 = 1) do={:return "one"} else={:return "not one"}}
:local var 2
:put [$func $var]
:set var 1
:put [$func $var]
}

results in the terminal code

not one
one
 
infabo
Forum Veteran
Forum Veteran
Posts: 752
Joined: Thu Nov 12, 2020 12:07 pm

Re: Graphs download script

Tue Dec 26, 2023 1:15 pm

holy batman, OP is resistant to improvement. rextended may not be polite sometimes, but you can still listen to his refactoring suggestions.

as long as you don't publish your scripts, yep, you can stick with bad code style as long you understand it. u don't need to adhere docs because "it works" now, but don't complain if script breaks silently after a ROS release.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12032
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Graphs download script

Tue Dec 26, 2023 3:06 pm

(thanks infabo)
 
dfdf
newbie
Topic Author
Posts: 36
Joined: Wed Dec 08, 2021 3:51 pm

Re: Graphs download script

Wed Dec 27, 2023 2:08 am

u don't need to adhere docs because "it works" now, but don't complain if script breaks silently after a ROS release.
well, it doesn't work as documented just now already, so until Mikrotik will decide to completely redo parsing engine, all such "requirements" sounds at least funny. Take a look at doc: https://help.mikrotik.com/docs/display/ROS/Scripting
Operations with Arrays
Warning: Key name in the array contains any character other than a lowercase character, it should be put in quotes
[admin@] > :local g {g=2}; :put ($g->g)       
[admin@] > :local g {g=2}; :put [:typeof ($g->g)]
nothing
[admin@] > :local g {g=2}; :put ($g->"g")          
2
[admin@] > 
HA-HA-HA. I already have to complain? Nope, just use what we have and DON'T complain. Why? Cause I have enough sense of understanding how parsing engine works and how difficult is to redo/rewrite it, taking into account low memory conditions in a bunch of Mikrotik devices. If I ALREADY see some flaws in it, than I DO UNDERSTAND "script may breaks silently", and, unfortunately, regardless of my efforts for refactoring.
 
optio
Long time Member
Long time Member
Posts: 696
Joined: Mon Dec 26, 2022 2:57 pm

Re: Graphs download script

Wed Dec 27, 2023 2:18 pm

Referring to warning from help you quoted is misleading, that warning is for key name used for setting values by key in array declaration (k=v), not accessing member by key with -> operator, it’s clearly understandable by example below that text or any other example in help, there is no example accessing value by -> without quotation for key names.
 
dfdf
newbie
Topic Author
Posts: 36
Joined: Wed Dec 08, 2021 3:51 pm

Re: Graphs download script

Wed Dec 27, 2023 4:54 pm

there is no example accessing value by -> without quotation for key names.
It's not obvious at all. The words "Key name in the array" are suitable for either case - whether in the declaration of the array, or in any other place where this key can be used. However, my initial idea was that, unfortunately, because of the way the parsing engine is currently implemented, it makes no sense to appeal to write scripts in the only documented way.
 
optio
Long time Member
Long time Member
Posts: 696
Joined: Mon Dec 26, 2022 2:57 pm

Re: Graphs download script

Wed Dec 27, 2023 5:26 pm

If there are no examples it will be confusing I agree, but examples explains usage, in -> operator usage example in help is key with quotation. I always examine examples to be certain about syntax when some usage is not consistent in different contexts.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12032
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Graphs download script

Wed Dec 27, 2023 5:36 pm

:local g {g=2}; :put ($g->g)
You like useless mixes, like g used as variable and as key name...


Operations with Arrays
Warning: Key name in the array contains any character other than a lowercase character, it should be put in quotes
The doc is correct:
[admin@] > :local g {f=2}; :put ($g->f)  ; # error, and f is red on terminal (not on syntax highlith on forum)....

[admin@] > :local g {f=2}; :put ($g->"f")  
2
[admin@] > :local g {ff=2}; :put ($g->"ff")    
2
[admin@] > :local g {fRf=2}; :put ($g->"fRf") ; # error, quotes not used and on terminal first fRf is already red

[admin@] > :local g {"fRf"=2}; :put ($g->"fRf")
2
[admin@] > 

You don't have to worry about proving something, you're already proving it very well.

Who is online

Users browsing this forum: No registered users and 10 guests