Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Why does the array not reset each time I call the function?

by tuxy94 (Initiate)
on Apr 02, 2008 at 08:20 UTC ( #677911=perlquestion: print w/replies, xml ) Need Help??

tuxy94 has asked for the wisdom of the Perl Monks concerning the following question:

I do not understand why the variable @data_file keeps the data from the previous call. My goal is to use this in order to clean a file from specific lines I do not desire, I do so, but if I run this method twice, it will append the data of the current call after the data from the previous call. Is there a way I can reset the @data_file each time the function is called or is there something I can do to help? Here is the code: (do not be too hard I have only been coding in Perl for the past 2 days!) Thanks a lot.

#!/usr/bin/perl ################### #Packages required# ################### use strict; use List::MoreUtils qw(uniq); use Data::Dumper; ############ #Parameters# ############ #First we define the path to the file we use #do not put any / my $dac02_location = "/dac03_scripts"; my $dac03_location = "/dac03_scripts/etc"; #name of the groups my @group = ('jai', 'smbuser', 'domadm'); #number of max user on the system my $i = 8; #name of additional machines that are in passwd but not in group my @add_machines=('dacsrv01$', 'dacwks01$', 'dacwks02$', 'dacwks03$', +'dacwks04$', 'dacwks05$', 'daceufo201$', 'dacluxe02$', 'dacluxe03$'); #special users to also update the password for my @special_users=('root', 'nagios'); ########### #Functions# ########### #To parse the data and store it in a hash sub DataParsing{ my ($file, @fields) = @_; my %data = (); my $item; open(DATA, $dac02_location."/".$file) or die "Cannot open the file +!"; while(<DATA>){ chomp; foreach $item (@fields){ if($_ =~ /$item/){ $data{$item}=[split('[:,]',$_)]; $data{$item.'_raw'} = $_; } } } close(DATA); return %data; } #Clean the file group and return an array with clean data to construct + the new one sub CleanFiles{ my ($file, @lines) = @_; my @data_file = (); open(DATA, $dac03_location."/".$file) or die "Cannot open the file +!"; #Store the text in an array, easier to work with while(<DATA>){ chomp; push(@data_file,$_); } close(DATA); #initialize a value to count where we are in the array in order to #delete the lines we do not need my $i = 0; my $item; my $item2; foreach $item (@data_file){ foreach $item2 (@lines){ if ($item =~ /$item2/){ splice(@data_file,$i,1); } } $i++ } # foreach $item (@data_file){ # print "$item\n"; # } return @data_file; } #function to generate the new config files sub CreateConfig{ my ($file,@data) = @_; my $item; $file = $file.".new"; open(NFILE,">$file"); foreach $item (@data){ printf NFILE "$item\n"; } close(NFILE); return $file; } ########### #Instances# ########### #hash of the group with the group name as reference my %group = DataParsing('group', @group); #print "$group{jai}[2]\n"; #put the usernames in an array to get info out of passwd my $item; my @username = (); foreach $item (@group){ for ($a = $i+1; $a > 2; $a--){ if($group{$item}[$a] ne ''){ push(@username,$group{$item}[$a]) } } } #array containing all of the user that need to be added on system my @usernames = (); @usernames=uniq(@username,@add_machines); my @special_usernames = uniq(@usernames,@special_users); #hash of the user in passwd with username as reference my %passwd = DataParsing('passwd',@special_usernames); #hash of the password in shadow with username as reference my %shadow = DataParsing('shadow',@special_usernames); ######################################################## ######################################################## my @group_clean_data = CleanFiles('group',@group); my @passwd_clean_data = CleanFiles('passwd',@special_usernames); print Dumper(@passwd_clean_data);

Replies are listed 'Best First'.
Re: Why does the array not reset each time I call the function?
by Lu. (Hermit) on Apr 02, 2008 at 08:46 UTC
    Hi,

    First, a good practice would be to always turn on warnings (use warnings;), it may give you hints as to what could be the problem.

    Then, the filehandle DATA is quite special in Perl, usually being used to read data stored in the program file. Try changing it to something else.

    Lu.
Re: Why does the array not reset each time I call the function?
by jwkrahn (Monsignor) on Apr 02, 2008 at 12:45 UTC
    73: #initialize a value to count where we are in the array in orde +r to 74: #delete the lines we do not need 75: my $i = 0; 76: my $item; 77: my $item2; 78: foreach $item (@data_file){ 79: foreach $item2 (@lines){ 80: if ($item =~ /$item2/){ 81: splice(@data_file,$i,1); 82: } 83: } 84: $i++ 85: }

    From the perlsyn man page:   <QUOTE>If any part of LIST is an array, "foreach" will get very confused if you add or remove elements within the loop body, for example with "splice". So donít do that. </QUOTE> Also you should quotemeta any outside data used in a regular expression.

    You can accomplish what you want like this:

    #initialize a value to count where we are in the array in order to #delete the lines we do not need foreach my $index ( reverse 0 .. $#data_file ) { foreach my $item ( @lines ) { if ( $data_file[ $index ] =~ /\Q$item/ ) { splice @data_file, $index, 1; } } }
Re: Why does the array not reset each time I call the function?
by wrinkles (Pilgrim) on Apr 02, 2008 at 10:09 UTC
    I do not understand why the variable @data_file keeps the data from the previous call.
    The array is not keeping the data, your data file is keeping it. I believe that you are reading the the data from your file into @data_file here:
    open(DATA, $dac03_location."/".$file) or die "Cannot open the file +!"; #Store the text in an array, easier to work with while(<DATA>){ chomp; push(@data_file,$_); } close(DATA);
      Thanks, yes I am reading the data from my file to place it in @data_file. But by doing close(DATA); am I not clearing all what could have been saved in DATA?
Re: Why does the array not reset each time I call the function?
by parv (Vicar) on Apr 02, 2008 at 08:50 UTC

    The style of your code in assignment to @add_machines is quite bothersome while reading it here on web, with my favourite editor inaccessible.

    Please add a space after a comma (if not before a comma too) so that long lines fold on space break, making reading possible.

    Note also that you do not need to escape characters, other than single quote itself, inside single quotes.

Re: Why does the array not reset each time I call the function?
by ikegami (Pope) on Apr 02, 2008 at 09:06 UTC

    I do not understand why the variable @data_file keeps the data from the previous call.

    I find that hard to believe. But since you didn't provide code I can run (or rather the data needed to run it), there's not much I can do about it.

      The data needed to run this are a shadow file, a passwd file and a group file from a Linux system. This script is supposed to parse the files, retrieve some specific groups, users from those groups and of course the password and then regenerate the new file in order to have them used in another linux server.

        Having just implemented something that does exactly what you describe, I have one recommendation: use Text::CSV_XS. Treat the passwd, group, and shadow files as CSVs separated by ':'. Build data structures, compare then, then use the same module to output the new files.

        You will save yourself a lot of hassle.

        Also, don't use DATA as the name of a file handle, it's special. Also, always use strict and warnings. You'll save yourself loads of debugging time.

        <radiant.matrix>
        Ramblings and references
        The Code that can be seen is not the true Code
        I haven't found a problem yet that can't be solved by a well-placed trebuchet
Re: Why does the array not reset each time I call the function?
by duff (Parson) on Apr 02, 2008 at 12:44 UTC

    How do you know that @data_file keeps values from previous use? @data_file is lexical to the CleanFiles() subroutine. Each time you call CleanFiles() you're going to get a fresh @data_file (that's how my works). Are you sure about what you're seeing?

      I do not think I am crazy, here is the new code, thanks to advices I got and I printed out the output also... Tell me if I am crazy. But yes, data_file is reset each time, as I try to print it, but for some reason, somewhere the data stays and it is added when I call the function again. Any other idea? Thanks
      #!/usr/bin/perl ################### #Packages required# ################### use strict; use List::MoreUtils qw(uniq); use Data::Dumper; use warnings; ############ #Parameters# ############ #First we define the path to the file we use #do not put any / my $dac02_location = "/dac03_scripts"; my $dac03_location = "/dac03_scripts/etc"; #name of the groups my @group = ('jai','smbuser','domadm'); #number of max user on the system my $i = 8; #name of additional machines that are in passwd but not in group my @add_machines=('dacsrv01\$', 'dacwks01\$', 'dacwks02\$', 'dacwks03\ +$', 'dacwks04\$', 'dacwks05\$', 'daceufo201\$', 'dacluxe02\$', 'daclu +xe03\$'); #special users to also update the password for my @special_users=('root','nagios'); ########### #Functions# ########### #To parse the data and store it in a hash sub DataParsing{ my ($file, @fields) = @_; my %data = (); my $item; open(DATA_PARSING, $dac02_location."/".$file) or die "Cannot open +the file!"; while(<DATA_PARSING>){ chomp; foreach $item (@fields){ if($_ =~ /$item/){ $data{$item}=[split('[:,]',$_)]; $data{$item.'_raw'} = $_; } } } close(DATA_PARSING); return %data; } #Clean the file group and return an array with clean data to construct + the new one sub CleanFiles{ my ($file, @lines) = @_; my @data_file = (); print "Dump of data_file in function:\n"; print Dumper(@data_file); open(DATA_CLEANING, $dac03_location."/".$file) or die "Cannot open + the file!"; #Store the text in an array, easier to work with while(<DATA_CLEANING>){ chomp; push(@data_file,$_); } close(DATA_CLEANING); #initialize a value to count where we are in the array in order to #delete the lines we do not need foreach my $index (reverse 0 .. $#data_file){ foreach my $item (@lines){ if ($data_file[$index] =~ $item){ splice @data_file, $index, 1; } } } # my $i = 0; # my $item; # my $item2; # foreach $item (@data_file){ # foreach $item2 (@lines){ # if ($item =~ /$item2/){ # splice(@data_file,$i,1); # } # } # $i++ # } # foreach $item (@data_file){ # print "$item\n"; # } return @data_file; } #function to generate the new config files sub CreateConfig{ my ($file,@data) = @_; my $item; $file = $file.".new"; open(NFILE,">$file"); foreach $item (@data){ printf NFILE "$item\n"; } close(NFILE); return $file; } ########### #Instances# ########### #hash of the group with the group name as reference my %group = DataParsing('group', @group); #print "$group{jai}[2]\n"; #put the usernames in an array to get info out of passwd my $item; my @username = (); foreach $item (@group){ for ($a = $i+1; $a > 2; $a--){ if($group{$item}[$a] ne ''){ push(@username,$group{$item}[$a]) } } } #array containing all of the user that need to be added on system my @usernames = (); @usernames=uniq(@username,@add_machines); my @special_usernames = uniq(@usernames,@special_users); #hash of the user in passwd with username as reference my %passwd = DataParsing('passwd',@special_usernames); #hash of the password in shadow with username as reference my %shadow = DataParsing('shadow',@special_usernames); ######################################################## ######################################################## my @group_clean_data = CleanFiles('group',@group); my @passwd_clean_data = CleanFiles('passwd',@special_usernames); print "Print of the group_clean_data outside of function:\n"; print Dumper(@group_clean_data); print "Print of passwd_clean_data outside of function:\n"; print Dumper(@passwd_clean_data);
      Here is the output of the script:
      Dump of data_file in function: Dump of data_file in function: Print of the group_clean_data outside of function: $VAR1 = 'root:x:0:'; $VAR2 = 'daemon:x:1:'; $VAR3 = 'bin:x:2:'; $VAR4 = 'sys:x:3:'; $VAR5 = 'adm:x:4:'; $VAR6 = 'tty:x:5:'; $VAR7 = 'disk:x:6:'; $VAR8 = 'lp:x:7:'; $VAR9 = 'mail:x:8:'; $VAR10 = 'news:x:9:'; $VAR11 = 'uucp:x:10:'; $VAR12 = 'man:x:12:'; $VAR13 = 'proxy:x:13:'; $VAR14 = 'kmem:x:15:'; $VAR15 = 'dialout:x:20:reyndce'; $VAR16 = 'fax:x:21:'; $VAR17 = 'voice:x:22:'; $VAR18 = 'cdrom:x:24:reyndce'; $VAR19 = 'floppy:x:25:reyndce'; $VAR20 = 'tape:x:26:'; $VAR21 = 'sudo:x:27:'; $VAR22 = 'audio:x:29:reyndce'; $VAR23 = 'dip:x:30:'; $VAR24 = 'www-data:x:33:apache'; $VAR25 = 'backup:x:34:'; $VAR26 = 'operator:x:37:'; $VAR27 = 'list:x:38:'; $VAR28 = 'irc:x:39:'; $VAR29 = 'src:x:40:'; $VAR30 = 'gnats:x:41:'; $VAR31 = 'shadow:x:42:'; $VAR32 = 'utmp:x:43:'; $VAR33 = 'video:x:44:reyndce'; $VAR34 = 'sasl:x:45:'; $VAR35 = 'plugdev:x:46:reyndce'; $VAR36 = 'staff:x:50:'; $VAR37 = 'games:x:60:'; $VAR38 = 'users:x:100:'; $VAR39 = 'nogroup:x:65534:'; $VAR40 = 'crontab:x:101:'; $VAR41 = 'Debian-exim:x:102:'; $VAR42 = 'ssh:x:103:'; $VAR43 = 'reyndce:x:1000:'; $VAR44 = 'mysql:x:104:'; $VAR45 = 'ssl-cert:x:105:'; $VAR46 = 'postfix:x:106:'; $VAR47 = 'postdrop:x:107:'; $VAR48 = 'nagios:x:1001:'; $VAR49 = 'nagcmd:x:1002:nagios,www-data'; $VAR50 = 'bind:x:108:'; $VAR51 = 'ntp:x:109:'; $VAR52 = 'apache:x:72:'; $VAR53 = 'slocate:x:110:'; Print of passwd_clean_data outside of function: $VAR1 = 'daemon:x:1:'; $VAR2 = 'bin:x:2:'; $VAR3 = 'sys:x:3:'; $VAR4 = 'adm:x:4:'; $VAR5 = 'tty:x:5:'; $VAR6 = 'disk:x:6:'; $VAR7 = 'lp:x:7:'; $VAR8 = 'mail:x:8:'; $VAR9 = 'news:x:9:'; $VAR10 = 'uucp:x:10:'; $VAR11 = 'man:x:12:'; $VAR12 = 'proxy:x:13:'; $VAR13 = 'kmem:x:15:'; $VAR14 = 'fax:x:21:'; $VAR15 = 'voice:x:22:'; $VAR16 = 'tape:x:26:'; $VAR17 = 'sudo:x:27:'; $VAR18 = 'dip:x:30:'; $VAR19 = 'www-data:x:33:apache'; $VAR20 = 'backup:x:34:'; $VAR21 = 'operator:x:37:'; $VAR22 = 'list:x:38:'; $VAR23 = 'irc:x:39:'; $VAR24 = 'src:x:40:'; $VAR25 = 'gnats:x:41:'; $VAR26 = 'shadow:x:42:'; $VAR27 = 'utmp:x:43:'; $VAR28 = 'sasl:x:45:'; $VAR29 = 'staff:x:50:'; $VAR30 = 'games:x:60:'; $VAR31 = 'users:x:100:'; $VAR32 = 'nogroup:x:65534:'; $VAR33 = 'crontab:x:101:'; $VAR34 = 'Debian-exim:x:102:'; $VAR35 = 'ssh:x:103:'; $VAR36 = 'mysql:x:104:'; $VAR37 = 'ssl-cert:x:105:'; $VAR38 = 'postfix:x:106:'; $VAR39 = 'postdrop:x:107:'; $VAR40 = 'bind:x:108:'; $VAR41 = 'ntp:x:109:'; $VAR42 = 'apache:x:72:'; $VAR43 = 'slocate:x:110:'; $VAR44 = 'daemon:x:1:1:daemon:/usr/sbin:/bin/sh'; $VAR45 = 'bin:x:2:2:bin:/bin:/bin/sh'; $VAR46 = 'sys:x:3:3:sys:/dev:/bin/sh'; $VAR47 = 'sync:x:4:65534:sync:/bin:/bin/sync'; $VAR48 = 'games:x:5:60:games:/usr/games:/bin/sh'; $VAR49 = 'man:x:6:12:man:/var/cache/man:/bin/sh'; $VAR50 = 'lp:x:7:7:lp:/var/spool/lpd:/bin/sh'; $VAR51 = 'mail:x:8:8:mail:/var/mail:/bin/sh'; $VAR52 = 'news:x:9:9:news:/var/spool/news:/bin/sh'; $VAR53 = 'uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh'; $VAR54 = 'proxy:x:13:13:proxy:/bin:/bin/sh'; $VAR55 = 'www-data:x:33:33:www-data:/var/www:/bin/sh'; $VAR56 = 'backup:x:34:34:backup:/var/backups:/bin/sh'; $VAR57 = 'list:x:38:38:Mailing List Manager:/var/list:/bin/sh'; $VAR58 = 'irc:x:39:39:ircd:/var/run/ircd:/bin/sh'; $VAR59 = 'gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gn +ats:/bin/sh'; $VAR60 = 'nobody:x:65534:65534:nobody:/nonexistent:/bin/sh'; $VAR61 = 'Debian-exim:x:100:102::/var/spool/exim4:/bin/false'; $VAR62 = 'statd:x:101:65534::/var/lib/nfs:/bin/false'; $VAR63 = 'identd:x:102:65534::/var/run/identd:/bin/false'; $VAR64 = 'sshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin'; $VAR65 = 'mysql:x:103:104:MySQL Server,,,:/var/lib/mysql:/bin/false'; $VAR66 = 'postfix:x:105:106::/var/spool/postfix:/bin/false'; $VAR67 = 'bind:x:106:108::/var/cache/bind:/bin/false'; $VAR68 = 'ntp:x:107:109::/home/ntp:/bin/false';

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://677911]
Approved by bingos
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (3)
As of 2021-10-27 07:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My first memorable Perl project was:







    Results (91 votes). Check out past polls.

    Notices?