Begginer alert!!
I have just started learning perl and have got stuck. I need to initialize a hash array with values from a list. I've been told to do this using a split command, but its just not happening.
Here is the script and output:
SCRIPT:
#!/bin/perl
system("clear");
@ARGV=("data");
%arr_data=();
while(<>){
chomp;
($name,$ext) = split;
if ($name){
$arr_data{$name} = "$ext";
}
$arr_data{$number}=$name;
}
until ($x eq x){
print "Please enter name, enter l for list, q for quit or f to find\n";
chomp($name = <STDIN>);
if ($name eq "l"){
while (($key,$value)=each(%arr_data)){
print "Name: $value\tExt: $key\n";
}
} elsif ($name eq "f"){
print "Please enter name\n";
chomp($find_name = <STDIN>);
$ext=$arr_data{$find_name};
if($ext eq ""){
print "Name not found\n";
} else {
print "Ext: $arr_data{$find_name}\n";
}
} elsif ($name eq "q"){
$x=x;
}else {
print "Please enter extention number\n";
chomp($ext = <STDIN>);
$arr_data{$ext}=$name;
}
}
*added code tags for readability -Optimus_P
..having bad day, submitted that before I'd finished!! 
and here is the output:
Please enter name, enter l for list, q for quit or f to find
l
Name: Ext:
Name: Ext: Tracy
Name: Ext: Chet
Name: Ext: Kemi
Name: Ext: Simon
Name: Ext: Dawn
Name: Ext: 3161
Name: Ext: 68843
Name: Ext: 68942
Name: Ext: 68944
Name: Ext: Marcie
Name: Ext: 3375
Name: ' Ext: s
Name: Ext: 5734
Name: Ext: 68895
Name: Ext: 68968
Name: Ext: Ella
Name: Ext: Ken
Please enter name, enter l for list, q for quit or f to find
q
(dev,discordia) >
The list i'm inputting looks like this:
(dev,discordia) > cat data
Dawn
68968
Ella
5734
Marcie
68942
Tracy
68895
Ken
3161
Chet
3375
Simon
68843
Kemi
68944
Cheers,
Cath
Okay. <> reads line by line, and therefore the thingy to be split() is actually just a single line, and there is no space to split (default split character is a space), so you get that funny result.
Just use a boolean counter to track whether you are reading an odd/even numbered (and that in turn tells whether that line is a name or extension) then, if that is a name, then output "Name:" and then the name read. otherwise "Ext:" and the extension printed. An if-else loop inside the while(<>) loop should be sufficient already.
1) your data file is inconsistant w/ how your program works.
2) the way you are populateing your hash is inconsistant
3) your last else statement does nothing.
4) you have various code flaws.
always use the -w switch when codeing.
get into the habbit of useing strict.
take a look at my reworked example of your script and you will notice a differance.
one thing i would highly suggest is when you are populating the hash lowercase all the names and lowercase all the userinput for the "find" option.
[qgatu003]/export/home/mxdooley$cat test.pl
#!/usr/bin/perl -w
use strict;
system("clear");
open (DATA, "./data") || die "Can NOT open file. ($!)";
my %arr_data;
while(<DATA>){
chomp;
my ($name, $ext) = split;
die "You have DUPLICATE NAMES fix this problem\n" if $arr_data{$name} ;
$arr_data{$name} = "$ext";
}
my $option;
my $key;
my $value;
my $name;
my $ext;
my $x;
until ($x=0){
print "Please enter option, enter l for list, q for quit or f to find\n";
chomp($option = <STDIN> );
if ($option eq "l"){
while (($key,$value)=each(%arr_data)){ print "Name: $key\tExt: $value\n"; };
} elsif ($option eq "f"){
print "Please enter name\n";
chomp($name=<STDIN>);
if (exists $arr_data{$name}) {
$ext=$arr_data{$name};
if(undef $ext) {
print "Ext not found\n";
} else {
print "Ext: $arr_data{$name}\n";
}
} else {
print "Name not Found\n";
}
} elsif ($option eq "q"){
die "You have quit the Program\n";
}
}
[qgatu003]/export/home/mxdooley$cat data
Dawn 68968
Ella 5734
Marcie 68942
Tracy 68895
Ken 3161
Chet 3375
Simon 68843
Kemi 68944
[qgatu003]/export/home/mxdooley$
if your data is how you listed it:
name
number
name
number
....
....
then what you could do to populate your hash is:
1) use a regex to test weither the line you just read in was either a word or a number (or series of).
OR
2) you could try to use the $. variable.
From the Programming Perl:
$.
[ALL] The current record number (usually line number) for the last filehandle you
read from (or called seek or tell on). The value may be different from the actual physical
line number in the file, depending on what notion of "line" is in effect
--see $/ ($INPUT_RECORD_SEPARATOR) on how to affect that. An explicit close on a filehandle
resets the line number. Because <> never does an explicit close, line numbers increase across
ARGV files (but see examples under eof). Localizing $. also localizes Perl's notion of "the last
read filehandle". (Mnemonic: many programs use "." to mean the current line number.)
wow, that's really good.
Thanks, I understand it more now. 