Array Initialization in Expect script - shell

How do you initialize an array in expect-send script? We can initialize a variable using
set Variable_name value. Likewise how can an array be initiated in expect-send script?

I assume you mean array as in associative array, not array as in C-like numerically-indexed list. You use the array set command:
array set varname {key1 val1 key2 val2 key3 val3 ... ...}
Since the contents of braces are not evaluated by Tcl (hence by expect), you can make it pretty if you want
array set varname {
key1 val1
key2 val2
.... ....
}
You can also assign the array elements directly:
set varname(key1) val1
set varname(key2) val2
...

Note that unlike set used to set a variable, array set works differently:
In the same tclsh:
% array set a {key1 val1 key2 val2}
% parray a
a(key1) = val1
a(key2) = val2
#This will not delete the content of the array:
% array set a {}
% parray a
a(key1) = val1
a(key2) = val2
#This will add new key-value pair:
% array set a {key3 val3}
% parray a
a(key1) = val1
a(key2) = val2
a(key3) = val3
#Array keys are unique:
% array set a {key1 val1 key2 val2}
% parray a
a(key1) = val1
a(key2) = val2
a(key3) = val3
#To unset the entire array content:
array unset a *
#To unset the array:
array unset a

Related

Find location of a value in a hash in Ruby

I have a hash list and I want to find when a user gives a value if that value comes after or before a target key in the list.
So for example I have the following list
my_list = {
key1 => value1,
key2 => value2,
key3 => value3,
key4 => value4
}
Then the user chooses key2 then it has a target key that was chosen let's say was key3
So my function will check if key2 comes before or after the target key, in this case key3.
If it was an array I would check which index the value is. But in a hash I am not sure how to do.
You can create a simple sequence look-up table with almost zero effort:
MY_LIST = {
start: 'Start',
middle: 'Middle?',
end: 'End!'
}
MY_LIST_SEQ = MY_LIST.keys.each_with_index.to_h
Now you have something that looks like this:
{:start=>0, :middle=>1, :end=>2}
Which means you can do this:
if MY_LIST_SEQ[a] > MY_LIST_SEQ[b]
# ...
end
No need to use a linear scan each time you want to look something up.

Perl: Using data from an anonymous hash

I am adding on to another developers code, we are both new to perl I am trying to take a list of IPs and run it through whois. I am unsure how to access the data in the anonymous hash, how do I use it?
He told me the data was stored inside one. This is the only instance I could find mentioning a hash:
## Instantiate a reference to an anonymous hash (key value pair)
my $addr = {};
The anonymous hash is the {} part. It returns a reference which can be stored in a scalar variable, like in your example:
my $addr = {};
To see the structure, you can print it with Data::Dumper:
use Data::Dumper;
print Dumper $addr;
It might show you something like:
$VAR1 = {
'c' => 1,
'a' => 2
};
You access the hash keys using the arrow operator:
print $addr->{"a"}
Like how you would access a regular hash, but with the arrow operator in between.
You can dereference the reference by putting a hash sigil in front
%$addr
# compare %addr %$addr
# hash hashref dereferenced
Here is an anonymous hash:
my $anon_hash = {
key1 => 'Value 1',
key2 => 'Value 2',
key3 => 'Value 3',
}
If you want to access an individual value:
my $value = $anon_hash->{key1};
say $anon_hash->{key2};
If you want to update an individual value:
$anon_hash->{key3} = 'New value 3';
If you want to add a new key/value pair:
$anon_hash->{key4} = 'Value 4';
You can also use all of the standard hash functions (e.g. keys()). You just need to "deference" your hash reference - which means putting a '%' in front of it.
So, for example, to print all the key/value pairs:
foreach my $key (keys %$anon_hash) {
say "$key : $anon_hash->{$_}";
}

Creating an enum from its name not value

Given the enumeration
enum NATO (:alpha<A>, :bravo<B>, :charlie<C>, :delta<D>);
it's possible to easily set a variable by literally typing one of the names, or by passing one of the values to the enum object:
my $a = alpha;
my $b = NATO('B');
say $a; # ↪︎ alpha
say $b; # ↪︎ bravo
say $a.value; # ↪︎ A
say $b.value; # ↪︎ B
Besides using EVAL and given a Str that corresponds to one of the enums, how could I create $c to be an enum value equivalent to charlie?
my $x = 'charlie';
my $c = ...
You can treat it as a Hash:
my $c = NATO::{$x};
You can use indirect name lookup:
enum NATO (:alpha<A>, :bravo<B>, :charlie<C>);
my $x = 'charlie';
my $c = ::($x);
say $c.value;

Invalid hex escape

There is my code :
var = "aa"
var2 = "bb"
var3 = "\x#{var}\x#{var2}"
And I want the "var3" to be hexadecimal.
But the error message is "Invalid hex escape". How can I fix that ?
This could help:
var3 = "#{var.hex.chr}#{var2.hex.chr}"
Your example does not work because \x has “higher priority” than string interpolation.
vars = [var, var2]
var3 = vars.pack('H*' * vars.size)
#⇒ "\xAA\xBB"
More info.
Another approach is this:
[var, var2].map { |s| '\x' + s }.join
Can you explain why you want var3 to be in that format? If it's to serialize the values, then another method might be simpler, e.g.:
require 'yaml'
[var, var2].to_yaml
# or
{ var: var, var2: var2 }.to_yaml
Lets say you want to send epoch timestamp as raw hexadecimal code, idea is simple create an array of bytes and then "pack" it (this will encode the string in the right way so it can be read and decode as hex code)
epoch_timestamp = 1631737774
epoch_hex = epoch_timestamp.to_s(16)
# epoch_hex is 4 bytes 614257a6
bytes = [epoch_hex[0..1], epoch_hex[2..3], epoch_hex[4..5], epoch_hex[6..7]]
bytes.pack('H*' * bytes.size)

How does one declare that a particular variable is an array?

I am looing for information on google about declaring array in expect but unable to find it.even the witki link for the line is empty.
I know i can set array values like set arr("hh") "hhh" but how do i declare it.
and can i print the whole array using one command or do i have to loop through it to print all the elements.
Or there is no such thing as declaring array in expect/tcl.i mean can we access any array
just by using global keyword.
You don't have to declare an array, but if you want to:
array set variableName {}
The last word is an empty list. If you have some default values you want to store in the array, you can say:
array set varname {key1 val1 key2 val2 ... ...}
If you're curious, here's how parray is implemented:
proc parray {a {pattern *}} {
upvar 1 $a array
if {![array exists array]} {
error "\"$a\" isn't an array"
}
set maxl 0
set names [lsort [array names array $pattern]]
foreach name $names {
if {[string length $name] > $maxl} {
set maxl [string length $name]
}
}
set maxl [expr {$maxl + [string length $a] + 2}]
foreach name $names {
set nameString [format %s(%s) $a $name]
puts stdout [format "%-*s = %s" $maxl $nameString $array($name)]
}
}
You don't declare arrays in Expect (or Tcl in general) you just use them.
But arrays and other variables do have scope. If you are in a proc and want to
refer to an array arr which has global scope you can either say global arr before
using it or prefix the name with :: each time you use it, eg. set ::arr(hh) "hhh"; puts $::arr(hh).
There is a command parray to print a whole array, but this is loaded from library scripts rather than being built-in, so may not be available depending on how your Expect installation has been done. Eg.
expect1.1> set arr(a) ACBD
ACBD
expect1.2> set arr(b) "BBB bbb"
BBB bbb
expect1.3> parray arr
arr(a) = ACBD
arr(b) = BBB bbb

Resources