Read values from INI file into string array - arrays

I have decided to have an accompanying .ini file with an executable so that I do not have to hard code items that appear in a drop down menu. I have created the .ini file and using the IniReadSection function I have been able to look through the section and output each Key=Value pair within that section.
How would I go about placing the value's only into a string array? I am writing this utility using AutoIT.

I made this ini file:
[JHamill]
key1=value1
key2=value2
key3=value3
I took a bit of code from IniReadSection example and modified this to be able to use it for a drop down menu.
$var = IniReadSection("test.ini", "JHamill")
$str = ""
For $i = 1 To $var[0][0]
$str &= $var[$i][1] & "|"
Next
$str = StringTrimRight($str, 1)
GUICreate("JHamill GUI combo")
GUICtrlCreateCombo("", 10, 10)
GUICtrlSetData(-1, $str)
GUISetState()
While 1
$msg = GUIGetMsg()
If $msg = -3 Then ExitLoop
WEnd
Here you see you don't have to make a new array to make it work. But since you asked, here is the same thing by making a new array first, copying only the value elements, and then using that array to fill the combo box:
#include <Array.au3>
$var = IniReadSection("test.ini", "JHamill")
Local $arr[$var[0][0]]
For $i = 1 To $var[0][0]
$arr[$i-1] = $var[$i][1]
Next
_ArrayDisplay($arr)

Related

How to create an array from a file in Powershell?

I want to read a file and load all its content to an array, one file line= one array member. from a weird reason- I don't manage to do it, it keep "merging" all the lines into 1 line.
I tried few ways-
1) Fetch the file content to list, and then
`$FilesList = New-Object System.Collections.Generic.List[String]
foreach($line in Get-Content $OutputFileName) {
$FilesList.Add($line)
}
This gives me good list, but then-
[String[]]$FilesArray = $FilesList.ToArray();
And I receive for-
$FilesArray[0] -> line1 line2 [0]
$FilesArray[1] -> line1 line2 [1]
2) Using the solution-
[string[]]$arrayFromFile = Get-Content -Path $OutputFileName
$arrayFromFile = [string[]](Get-Content -Path $OutputFileName)
Same result when printing $arrayFromFile[0] and $arrayFromFile[1]
3) Using the solution -
[String[]]$arrayFromFile = [IO.File]::ReadAllLines($OutputFileName)
Same result when printing $arrayFromFile[0] and $arrayFromFile[1]
What am I doing wrong, How can it be that I can create a list but not an array?
The problem is that I need to allow the client to choose between the values, so it is important to me to receive array that I can choose specific location
OK, found the problem. nothing to do with the array.
The problem was that the Write-Output can not receive as a parameter "$array[index]", it then prints the full array, and then the index itself.

Compare Elements in Array for While Loop - Powershell

I am attempting to create a script to read a CSV, then perform some operations on the contents where the first field are similar. Right now I'm stuck on trying to set up the second While loop to compare the current element to the next one.
I'm fairly new to this, because I wasn't getting anywhere trying this in Java. I can't seem to find a combination of commands that will let the loop work.
Some things I've tried are:
While($csv[$count].ip -eq $csv[$count++].ip)
While((diff $csv[count].ip $csv[$count++].ip) = true)
While($csv[$count].ip = $csv[$count++].ip)
Don't use $count++ unless you want to actually change the value of $count itself. Instead use $count + 1 as the array index
$count = 0
while($count -le $csv.Count){
if($csv[$count].ip -eq $csv[$count + 1].ip){
# Do your stuff here
}
$count++
}

Assigning range to an array in Perl

I have some mini problem. How can I assign a range into an array, like this one:
input file: clktest.spf
*
.GLOBAL vcc! vss!
*
.SUBCKT eclk_l_25h brg2eclk<1> brg2eclk<0> brg_cs_sel brg_out brg_stop cdivx<1>
+ eclkout1<24> eclkout1<23> eclkout1<22> eclkout1<21> eclkout1<20> eclkout1<19>
+ mc1_brg_dyn mc1_brg_outen mc1_brg_stop mc1_div2<1> mc1_div2<0> mc1_div3p5<1>
+ mc1_div3p5<0> mc1_div_mux<3> mc1_div_mux<2> mc1_div_mux<1> mc1_div_mux<0>
+ mc1_gsrn_dis<0> pclkt6_0 pclkt6_1 pclkt7_0 pclkt7_1 slip<1> slip<0>
+ ulc_pclkgpll0<1> ulc_pclkgpll0<0> ulq_eclkcib<1> ulq_eclkcib<0>
*
*Net Section
*
*|GROUND_NET 0
*
*|NET eclkout3<48> 2.79056e-16
*|P (eclkout3<48> X 0 54.8100 -985.6950)
*|I (RXR0<16>#NEG RXR0<16> NEG X 0 54.2255 -985.6950)
C1 RXR0<16>#NEG 0 5.03477e-17
C2 eclkout3<48> 0 2.28708e-16
Rk_6_1 eclkout3<48> RXR0<16>#NEG 0.110947
output (this should be the saved value in the array)
.SUBCKT eclk_l_25h brg2eclk<1> brg2eclk<0> brg_cs_sel brg_out brg_stop cdivx<1>
+ eclkout1<24> eclkout1<23> eclkout1<22> eclkout1<21> eclkout1<20> eclkout1<19>
+ mc1_brg_dyn mc1_brg_outen mc1_brg_stop mc1_div2<1> mc1_div2<0> mc1_div3p5<1>
+ mc1_div3p5<0> mc1_div_mux<3> mc1_div_mux<2> mc1_div_mux<1> mc1_div_mux<0>
+ mc1_gsrn_dis<0> pclkt6_0 pclkt6_1 pclkt7_0 pclkt7_1 slip<1> slip<0>
+ ulc_pclkgpll0<1> ulc_pclkgpll0<0> ulq_eclkcib<1> ulq_eclkcib<0>
*
*Net Section
my simple code:
#!/usr/bin/perl
use strict;
use warnings;
my $input = "clktest.spf";
open INFILE, $input or die "Can't open $input" ;
my #allports;
while (<INFILE>){
#allports = /\.SUBCKT/ ... /\*Net Section/ ;
print #allports;
}
I am doing a correct job of assigning the selected range into an array? If not how can I modify this code?
Thanks for advance.
The while loop only gives you one line at a time so you can't assign all of the lines you want at once. Use push instead to grow the array line by line.
Also, you should be using lexical file handles like $in_fh (rather than global ones like INFILE) with the three-parameter form of open, and you should include the $! variable in the die string so that you know why the open failed.
This is how your program should look
#!/usr/bin/perl
use strict;
use warnings;
my $input = 'clktest.spf';
open my $in_fh, '<', $input or die "Can't open $input: $!" ;
my #allports;
while ( <$in_fh> ) {
push #allports, $_ if /\.SUBCKT/ ... /\*Net Section/;
}
print #allports;
Note that, if all you want to do is to print the selected lines from the file, you can forget about the array and replace push #allports, $_ with print
The <INFILE> inside a while will read the file line-by-line, so not a right place to apply a regex which need to cover more than one line. In order to get a substring, the simplest way is to first join all these lines. And only after that you apply your regex.
my $contents = "";
while ( <INFILE> ) {
$contents = $contents . $_;
}
$contents =~ s/.*(\.SUBCKT.*\*Net Section).*/$1/s; # remove unneeded part
Please note that there is /s modifier in the last part of substitution line. This is required because $contents contains newlines.
To get the substring into array, just use split my #allports = split("\n", $contents);

Search for, and remove column from CSV file

I'm trying to write a subroutine that will take two arguments, a filename and the column name inside a CSV file. The subroutine will search for the second argument (column name) and remove that column (or columns) from the CSV file and then return the CSV file with the arguments removed.
I feel like I've gotten through the first half of this sub (opening the file, retrieve the headers and values) but I can't seem to find a way to search the CSV file for the string that the user inputs and delete that whole column. Any ideas? Here's what I have so far.
sub remove_columns {
my #Para = #_;
my $args = #Para;
die "Insufficent arguments\n" if ($nargs < 2);
open file, $file
$header = <file>;
chomp $header;
my #hdr = split ',',$header;
while (my $line = <file>){
chomp $line;
my #vals = split ',',$line;
#hash that will allow me to access column name and values quickly
my %h;
for (my $i=0; $i<=$#hdr;$i++){
$h{$hdr[$i]}=$i;
}
....
}
Here's where the search and removal will be done. I've been thinking about how to go about this; the CSV files that I'll be modifying will be huge, so speed is a factor, but I can't seem to think of a good way to go about this. I'm new to Perl, so I'm struggling a bit.
Here are a few hints that will hopefully get you going.
To remove the element of an array at position $index of an array use :
splice #array,$index,1 ;
As speed is an issues, you probably want to construct an array of column numbers at the start and then loop on the the elements of the array
for my $index (#indices) {
splice #array,$index,1 ;
}
(this way is more idiomatic Perl than for (my $i=0; $i<=$#hdr;$i++) type loop )
Another thing to consider - CSV format is surprisingly complicated. Might your data have data with , within " " such as
1,"column with a , in it"
I would consider using something like Text::CSV
You should probably look in the direction of Text::CSV
Or you can do something like this:
my $colnum;
my #columns = split(/,/, <$file>);
for(my $i = 0; $i < scalar(#columns); $i++) {
if($columns[$i] =~ /^$unwanted_column_name$/) {
$colnum = $i;
last;
};
};
while(<$file>) {
my #row = split(/,/, $_);
splice(#row, $colnum, 1);
#do something with resulting array #row
};
Side note:
you really should use strict and warnings;
split(/,/, <$file>);
won't work with all CSV files
There is elegant way how to remove some columns from array. If I have columns to removal in array #cols, and headers in #headers I can make array of indexes to preserve:
my %to_delete;
#to_delete{#cols} = ();
my #idxs = grep !exists $to_delete{$headers[$_]}, 0 .. $#headers;
Then it's easy to make new headers
#headers[#idxs]
and also new row from read columns
#columns[#idxs]
The same approach can be used for example for rearranging arrays. It is very fast and pretty idiomatic Perl way how to do this sort of tasks.

read multiple files using one loop perl

i have 2 files each having 50 lines..
FILE1
FILE2
now, i need to read two file lines by line in a single while or for loop and i should push the corresponding line to the 2 output arrays. i have tried something like this. but its not working out. kindly help
#!/usr/bin/perl
my #B =();
my #C =();
my #D =();
my $lines = 0;
my $i = 0;
my $sizeL = 0;
my $sizeR = 0;
my $gf = 0;
$inputFile = $ARGV[0];
$outputFile = $ARGV[1];
open(IN1FILE,"<$inputFile") or die "cant open output file ";
open(IN2FILE,"<$outputFile") or die "cant open output file";
while((#B=<IN1FILE>)&&(#C= <IN2FILE>))
{
my $line1 = <IN1FILE>;
my $line2 = <IN2FILE>;
print $line2;
}
Here array 2 is not getting build.. but i am getting array 1 value.
In your loop condition, you read the whole files into their arrays. The list assignment is then used as a boolean value. This works only once, as the files will be read after the condition has been evaluated. Also, the readlines inside the loop will return undef.
Here is code that should work:
my (#lines_1, #lines_2);
# read until one file hits EOF
while (!eof $INFILE_1 and !eof $INFILE_2) {
my $line1 = <$INFILE_1>;
my $line2 = <$INFILE_2>;
say "from the 1st file: $line1";
say "from the 2nd file: $line2";
push #lines_1, $line1;
push #lines_2, $line2;
}
You could also do:
my (#lines_1, #lines_2);
# read while both files return strings
while (defined(my $line1 = <$INFILE_1>) and defined(my $line2 = <$INFILE_2>)) {
say "from the 1st file: $line1";
say "from the 2nd file: $line2";
push #lines_1, $line1;
push #lines_2, $line2;
}
Or:
# read once into arrays
my #lines_1 = <$INFILE_1>;
my #lines_2 = <$INFILE_2>;
my $min_size = $#lines_1 < $#lines_2 ? $#lines_1 : $#lines_2; # $#foo is last index of #foo
# then interate over data
for my $i ( 0 .. $min_size) {
my ($line1, $line2) = ($lines_1[$i], $lines_2[$i]);
say "from the 1st file: $line1";
say "from the 2nd file: $line2";
}
Of course, I am assuming that you did use strict; use warnings; and use feature 'say', and used the 3-arg form of open with lexical filehandles:
my ($file_1, $file_2) = #ARGV;
open my $INFILE_1, '<', $file_1 or die "Can't open $file_1: $!"; # also, provide the actual error!
open my $INFILE_2, '<', $file_2 or die "Can't open $file_2: $!";
I also urge you to use descriptive variable names instead of single letters, and to declare your variables in the innermost possible scope — declaring vars at the beginning is almost the same as using bad, bad globals.

Resources