Issue with data stored in a file

Hello,
I have a specific issue.
i am downloading some data with /tool fetch command
Thecontent of that file is in correct Mikrotik array format, but when i load it into a variable, it is not recognised as an array, but as an ordinary string instead.
:toarray transforms this string into an array with a single element, which is the complete string.
file contents: {“A”=“1”;“B”=“test”;“C”=“20”;“D”=“test2”;}

:global data [/file get "file.txt" contents]
:put $data
{"A"="1";"B"="test";"C"="20";"D"="test2";}
:put [:typeof $data ]
str
:put [:toarray $data ]
"A"="1";"B"="test";"C"="20";"D"="test2";
:put ([:toarray $data ]->0)
"A"="1";"B"="test";"C"="20";"D"="test2";
:put ([:toarray $data ]->1)
  (empty)
:put ([:toarray $data ]->"A")
  (empty)

when i copy/paste this string into the terminal, the contents are correctly recognised as an array, and the elements can be called from it

:global data {"A"="1";"B"="test";"C"="20";"D"="test2";}
:put [:typeof $data]
array 
:put ($data->"A")
1
:put ($data->"B")
test

saving files like this also does not help

/file set test1 contents="{\"A\"=\"1\";\"B\"=\"test\";\"C\"=\"20\";\"D\"=\"test2\";}"

contents of the resulting file looks like this, and it has the same issue
{“A”=“1”;“B”=“test”;“C”=“20”;“D”=“test2”;}

:global data {"A"="1";"B"="test";"C"="20";"D"="test2";}
/file set test123 contents=$data

contents of the resulting file looks like this, but the issue is the same
A=1;B=test;C=20;D=test2

Only data directly pasted into the terminal is properly parsed, anything loaded from the file fails.

Essentially, i want some key->value stored, and read to be used in the script.

Any ideas?
Thanks

Any ideas?

Yes

You have see the page on the link on signatue and discovered something useful?

You need some hints?

You have a ton of interesting stuff, it will take some time to go through it all

{
:local filecontent [/file get "file.txt" contents]
:global tempconv
[:parse ":global tempconv $filecontent"]
:local arrayfromfile $tempconv
:put [:typeof $arrayfromfile]
:put ($arrayfromfile->"D")
}

Thank you! I will definitely test this.

But this is not the only issue I am experiencing with loading stuff from file.
I also have issues with executing imported scripts.
I’m running 7.4.1 from stable branch on RB951

This is a simple example I’ve made just for this demonstration:

:global username ""
:global password ""
;global hostname "test.local"

:global readInput do={
  :return
}

:global checkHost do={
  :global port "443"
  :if (:put [:find $hostname ".local"]) do={
    :global host [:pick $hostname 0 [:find $hostname ".local"]]
  } else={
    :global host $hostname
    :global hostname ($host . ".local")
  }
  :global url ("https://".$hostname.":".$port."/".$host)
  :put ("URL: " . $url)
}

:global checkCreds do={
  :if ([:len $username] = 0) do={
    :put "Please enter your username:"
    :global username [$readInput]
  }
  :if ([:len $password] = 0) do={
    :put "Please enter your password:"
    :global password [$readInput]
  }
  :put ("username: " . $username)
  :put ("password: " . $password)
}

The $checkCreds function just skips over, and asks nothing. $readInput is not processed.
:if in $checkHost returns false, instead of true, and the $hostname variable is not even evaluated.
This only applies if the script is loaded from the rsc file.
if the code is pasted directly in the terminal, everything works as expected.

Why is this behaviour so unpredictable?
What am I missing?

Okay, I’ve got it.

the globals need to be registered inside the functions, which, in hindsight, makes sense.
since functions are also variables in RouterOS, they need to be declared as well.
However, this inconsistency is ridiculous.
How can one thing work in terminal, but not in imported script.
The contents of the variables are exactly the same.
@RouterOS devs, please fix this.

For future reference this is the code that works:

:global username ""
:global password ""
;global hostname "test.local"

:global readInput do={
  :return
}

:global checkHost do={
  :global hostname
  :global host
  :global port "443"
  :global url

  :if (:put [:find $hostname ".local"]) do={
    :set host [:pick $hostname 0 [:find $hostname ".local"]]
  } else={
    :set host $hostname
    :set hostname ($host . ".local")
  }
  :set url ("https://".$hostname.":".$port."/".$host)
  :put ("URL: " . $url)
}

:global checkCreds do={
  :global readInput
  :global username
  :global password

  :if ([:len $username] = 0) do={
    :put "Please enter your username:"
    :set username [$readInput]
  }
  :if ([:len $password] = 0) do={
    :put "Please enter your password:"
    :set password [$readInput]
  }
  :put ("username: " . $username)
  :put ("password: " . $password)
}

I’m struggling with this same exact issue, and have had no luck. I see the response from rextended but the code snippet does not work (I’m not reading from a file, but using output=user for my fetch command, perhaps that changes things?) and I don’t see anything he’s posted before that solves the issue either.

Is this?
http://forum.mikrotik.com/t/using-fetch-to-get-an-array/162042/1

continue on that topic