Re: array within array
On Oct 29, 11:09 am, [EMAIL PROTECTED] (John W . Krahn) wrote: On Monday 29 October 2007 06:42, Mike Tran wrote: Hey all, Hello, I'm new with Perl and need help with this simple script. I'm still playing around with the script below to get a feel for Perl. My script below is incomplete and I'm doing an array within an array which is incorrect. Please help. You are not using arrays you are using hashes. Here's what I want to do; I have to flat files (pipe delimited, export from a database) that I want to parse through and assign variables for each column. Basically, I want to parse through exclude_bases.txt and do: if base_no in exclude_bases.txt equals to base_no in base.txt then search in the description field of base.txt for the string listed in the keyword field in exclude_bases.tx and replace with new_keyword in exclude_bases.txt and write the out put into a new file called new_bases.txt. Any suggestions on how I could accomplish the above task is greatly appreciated. Thanks all. Flat Files: base.txt: base_no|name|description 1|test|test desc 10001|test2|test desc 2 10002|test3|test desc 3 exclude_bases.txt: base_no|keyword|new_keyword| 1|test desc|testdesc|0 10001|test desc 2|testdesc2|0 10002|test desc 3|testdesc3|1 [snip] It looks like you may want something like this: #!/usr/bin/perl use strict; use warnings; my $exclude_bases = 'exclude_bases.txt'; my $current_base = 'base.txt'; my $output= 'new_bases.txt'; open EXCLUDE, '', $exclude_bases or die Could not open '$exclude_bases' $!; my %exclude_bases; while ( EXCLUDE ) { next if $. == 1; # exclude header chomp; my ( $exbase_no, $keyword, $new_keyword ) = split /\|/; $exclude_bases{ $exbase_no } = { from = qr/\Q$keyword/, to = $new_keyword }; } Since you're not taking into account the blank lines, you'll be generating these warnings: Use of uninitialized value in quotemeta at C:\test\JohnKrahn.pl line 17, EXCLUDE line 2. Use of uninitialized value in hash element at C:\test\JohnKrahn.pl line 17, EXCLUDE line 2. Use of uninitialized value in quotemeta at C:\test\JohnKrahn.pl line 17, EXCLUDE line 4. Use of uninitialized value in hash element at C:\test\JohnKrahn.pl line 17, EXCLUDE line 4. close EXCLUDE; open BASE, '', $current_base or die Could not open '$current_base' $!; open OUT, '', $outputor die Could not open '$output' $!; while ( BASE ) { my ( $base_no, $name, $description ) = split /\|/; if ( exists $exclude_bases{ $base_no } ) { $description =~ s/$exclude_bases{$base_no}{from}/$exclude_bases{$base_no}{to}/g; $_ = join '|', $base_no, $name, $description; } print OUT; } Again, blank lines are not taken into account, but no warnings since the printing is being handled within the conditional block. Since a complete solution, to what appears to be a homework question, has already been provided, I guess I'll show mine. #!/usr/bin/perl use warnings; use strict; my %base; open (my $new, '', 'new_bases.txt') || die new_bases.txt $!; open (my $exclude, '', 'exclude_bases.txt') || die exclude_bases.txt $!; open (my $base, '', 'base.txt') || die base.txt $!; while ($base) { next if /^\s*$/; # skip over blank lines print and next if $. == 1; # print header chomp; my @fields = split /\|/; $base{$fields[0]} = [EMAIL PROTECTED]; } close $base; while ($exclude) { next if /^\s*$/; # skip over blank lines chomp; my @fields = split /\|/; if ( exists $base{$fields[0]} and $fields[1] eq $base{$fields[0]} [2]) { $base{$fields[0]}[2] = $fields[2]; # if you want to retain the empty lines between records, # you can use \n\n in the print statement, # or reassign the output record separator print $new join('|', @{$base{$fields[0]}}), \n; } } close $exclude; close $new; -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/
Re: array within array
On 29 Oct 2007 at 8:42, Mike Tran wrote: Hey all, I'm new with Perl and need help with this simple script. I'm still playing around with the script below to get a feel for Perl. My script below is incomplete and I'm doing an array within an array which is incorrect. Please help. Here's what I want to do; I have to flat files (pipe delimited, export from a database) that I want to parse through and assign variables for each column. Basically, I want to parse through exclude_bases.txt and do: if base_no in exclude_bases.txt equals to base_no in base.txt then search in the description field of base.txt for the string listed in the keyword field in exclude_bases.tx and replace with new_keyword in exclude_bases.txt and write the out put into a new file called new_bases.txt. Any suggestions on how I could accomplish the above task is greatly appreciated. Thanks all. Flat Files: base.txt: base_no|name|description 1|test|test desc 10001|test2|test desc 2 10002|test3|test desc 3 exclude_bases.txt: base_no|keyword|new_keyword| 1|test desc|testdesc|0 10001|test desc 2|testdesc2|0 10002|test desc 3|testdesc3|1 #!/usr/bin/perl use strict; use warnings; my $exclude_bases = exclude_bases.txt; my $current_base = base.txt; my $output = new_bases.txt; my %exclude_bases; my $exclude_text; my $exbase_no; my $keyword; my $new_keyword; open(EXCLUDE,exclude_bases.txt )|| die(Could not open file!); %exclude_bases=EXCLUDE; close(EXCLUDE); my $base_no =; my $name=; my $description=; my $current_base=; my $base_text=; my %bases; open(BASE,base.txt)|| die(Could not open file!); %bases=BASE; close(BASE); #choping lines and assign variables to base.txt foreach $base_text (%bases) { chop($base_text); ($base_no,$name,$description)=split(/\|/,$base_text); #choping lines and assign variables to exclude_bases.txt foreach $exclude_text (%exclude_bases) { chop($exclude_text); ($exbase_no,$keyword,$new_keyword)=split(/\|/,$base_text); if ($exbase_no=$base_no) { $keyword =~ s/$keyword/$new_keyword/g;} Well here my effort. It should help you get closer to what your after but it's not complete. I would use hashes not arrays, you'll find them extremely useful for de-duping data I haven't run the script below, please do a perl -c first. Check out exists perldoc -f exists #!/usr/bin/perl use strict; # Well done use warnings; # ditto. my $exclude_bases = exclude_bases.txt; open(EXCLUDE,excludes.txt )|| die(Could not open file!); while (EXCLUDE) { chomp; my @fields = split(/|/,$_); $exclude_bases{$F[0]} = 0; # $f[0] contains base_no } close(EXCLUDE); open(BASE,base.txt)|| die(Could not open file!); while (BASE) { chomp; my @fields = split(/|/,$_); if (! exists($exlude_bases{$_}) ) { print $f[2]\n; } } close(BASE); HTH, Dp. -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/
RE: array within array
be very careful with exists, it auto creates the structure i.e. use Data::Dumper; my %hash; if (exists $hash{a}{b}) { } print Dumper(\%hash) then the next time you use exists it is there. defined is much safer as it doesnt do this. -Original Message- From: Beginner [mailto:[EMAIL PROTECTED] Sent: 29 October 2007 15:30 To: beginners @ perl. org Subject: Re: array within array On 29 Oct 2007 at 8:42, Mike Tran wrote: Hey all, I'm new with Perl and need help with this simple script. I'm still playing around with the script below to get a feel for Perl. My script below is incomplete and I'm doing an array within an array which is incorrect. Please help. Here's what I want to do; I have to flat files (pipe delimited, export from a database) that I want to parse through and assign variables for each column. Basically, I want to parse through exclude_bases.txt and do: if base_no in exclude_bases.txt equals to base_no in base.txt then search in the description field of base.txt for the string listed in the keyword field in exclude_bases.tx and replace with new_keyword in exclude_bases.txt and write the out put into a new file called new_bases.txt. Any suggestions on how I could accomplish the above task is greatly appreciated. Thanks all. Flat Files: base.txt: base_no|name|description 1|test|test desc 10001|test2|test desc 2 10002|test3|test desc 3 exclude_bases.txt: base_no|keyword|new_keyword| 1|test desc|testdesc|0 10001|test desc 2|testdesc2|0 10002|test desc 3|testdesc3|1 #!/usr/bin/perl use strict; use warnings; my $exclude_bases = exclude_bases.txt; my $current_base = base.txt; my $output = new_bases.txt; my %exclude_bases; my $exclude_text; my $exbase_no; my $keyword; my $new_keyword; open(EXCLUDE,exclude_bases.txt )|| die(Could not open file!); %exclude_bases=EXCLUDE; close(EXCLUDE); my $base_no =; my $name=; my $description=; my $current_base=; my $base_text=; my %bases; open(BASE,base.txt)|| die(Could not open file!); %bases=BASE; close(BASE); #choping lines and assign variables to base.txt foreach $base_text (%bases) { chop($base_text); ($base_no,$name,$description)=split(/\|/,$base_text); #choping lines and assign variables to exclude_bases.txt foreach $exclude_text (%exclude_bases) { chop($exclude_text); ($exbase_no,$keyword,$new_keyword)=split(/\|/,$base_text); if ($exbase_no=$base_no) { $keyword =~ s/$keyword/$new_keyword/g;} Well here my effort. It should help you get closer to what your after but it's not complete. I would use hashes not arrays, you'll find them extremely useful for de-duping data I haven't run the script below, please do a perl -c first. Check out exists perldoc -f exists #!/usr/bin/perl use strict; # Well done use warnings; # ditto. my $exclude_bases = exclude_bases.txt; open(EXCLUDE,excludes.txt )|| die(Could not open file!); while (EXCLUDE) { chomp; my @fields = split(/|/,$_); $exclude_bases{$F[0]} = 0; # $f[0] contains base_no } close(EXCLUDE); open(BASE,base.txt)|| die(Could not open file!); while (BASE) { chomp; my @fields = split(/|/,$_); if (! exists($exlude_bases{$_}) ) { print $f[2]\n; } } close(BASE); HTH, Dp. -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/ This e-mail is from the PA Group. For more information, see www.thepagroup.com. This e-mail may contain confidential information. Only the addressee is permitted to read, copy, distribute or otherwise use this email or any attachments. If you have received it in error, please contact the sender immediately. Any opinion expressed in this e-mail is personal to the sender and may not reflect the opinion of the PA Group. Any e-mail reply to this address may be subject to interception or monitoring for operational reasons or for lawful business practices. -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/
Re: array within array
On Monday 29 October 2007 07:29, Beginner wrote: while (EXCLUDE) { chomp; my @fields = split(/|/,$_); ^^^ $exclude_bases{$F[0]} = 0; # $f[0] contains base_no } close(EXCLUDE); open(BASE,base.txt)|| die(Could not open file!); while (BASE) { chomp; my @fields = split(/|/,$_); ^^^ The '|' character has a special meaning in a regular expression so you have to escape it if you want to match a literal '|' character. John -- use Perl; program fulfillment -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/
Re: array within array
Andrew Curry schreef: be very careful with exists, it auto creates the structure use Data::Dumper; my %hash; if (exists $hash{a}{b}) {} print Dumper(\%hash) then the next time you use exists it is there. defined is much safer as it doesnt do this. No, the difference here is not between exists() and defined(). To be able to check the definedness (or the existence) of $h{foo}{bar}, $h{foo} is created first (auto-vivification). Neither exists() nor defined() short-cuts hash-levels. perl -MData::Dumper -wle' my %hash; if ( defined $hash{foo}{bar} ) {}; print Dumper \%hash; ' $VAR1 = { 'foo' = {} }; (same with exists()) Solution: test $h{foo} first: if ( exists( $hash{foo} ) and exists( $hash{foo}{bar} ) ) { ... } -- Affijn, Ruud Gewoon is een tijger. -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/
Re: array within array
On Monday 29 October 2007 06:42, Mike Tran wrote: Hey all, Hello, I'm new with Perl and need help with this simple script. I'm still playing around with the script below to get a feel for Perl. My script below is incomplete and I'm doing an array within an array which is incorrect. Please help. You are not using arrays you are using hashes. Here's what I want to do; I have to flat files (pipe delimited, export from a database) that I want to parse through and assign variables for each column. Basically, I want to parse through exclude_bases.txt and do: if base_no in exclude_bases.txt equals to base_no in base.txt then search in the description field of base.txt for the string listed in the keyword field in exclude_bases.tx and replace with new_keyword in exclude_bases.txt and write the out put into a new file called new_bases.txt. Any suggestions on how I could accomplish the above task is greatly appreciated. Thanks all. Flat Files: base.txt: base_no|name|description 1|test|test desc 10001|test2|test desc 2 10002|test3|test desc 3 exclude_bases.txt: base_no|keyword|new_keyword| 1|test desc|testdesc|0 10001|test desc 2|testdesc2|0 10002|test desc 3|testdesc3|1 #!/usr/bin/perl use strict; use warnings; my $exclude_bases = exclude_bases.txt; my $current_base = base.txt; my $output = new_bases.txt; my %exclude_bases; my $exclude_text; my $exbase_no; my $keyword; my $new_keyword; You should define variables in the smallest possible scope. open(EXCLUDE,exclude_bases.txt )|| die(Could not open file!); You have stored the file name in the $exclude_bases variable above so why do you not use the variable instead? You should include the $! variable in the error message so you know *why* it failed. %exclude_bases=EXCLUDE; You are assigning the list from the file to a hash. The list elements are defined by the value of the $/ variable so here each element of the list is a line from the file. Because you are assigning to a hash the first element is a key and the second element is the value for that key. if any of the keys (odd elements) are the same as a previous key then the old value will be overwritten by the new value and you will lose lines from the file. close(EXCLUDE); my $base_no =; my $name=; my $description=; my $current_base=; my $base_text=; my %bases; open(BASE,base.txt)|| die(Could not open file!); Same as above. %bases=BASE; Same as above. close(BASE); #choping lines and assign variables to base.txt foreach $base_text (%bases) { chop($base_text); You should use chomp() instead of chop(). ($base_no,$name,$description)=split(/\|/,$base_text); #choping lines and assign variables to exclude_bases.txt foreach $exclude_text (%exclude_bases) { chop($exclude_text); Same as above. ($exbase_no,$keyword,$new_keyword)=split(/\|/,$base_text); if ($exbase_no=$base_no) { You are assigning the value of $base_no to the variable $exbase_no. If the value of $base_no is true then the expression is true. You want to use a comparison operator like '==' or 'eq'. $keyword =~ s/$keyword/$new_keyword/g;} Your description said that you wanted to modify 'the description field of base.txt' so that sould be: $description =~ s/$keyword/$new_keyword/g;} } } It looks like you may want something like this: #!/usr/bin/perl use strict; use warnings; my $exclude_bases = 'exclude_bases.txt'; my $current_base = 'base.txt'; my $output= 'new_bases.txt'; open EXCLUDE, '', $exclude_bases or die Could not open '$exclude_bases' $!; my %exclude_bases; while ( EXCLUDE ) { next if $. == 1; # exclude header chomp; my ( $exbase_no, $keyword, $new_keyword ) = split /\|/; $exclude_bases{ $exbase_no } = { from = qr/\Q$keyword/, to = $new_keyword }; } close EXCLUDE; open BASE, '', $current_base or die Could not open '$current_base' $!; open OUT, '', $outputor die Could not open '$output' $!; while ( BASE ) { my ( $base_no, $name, $description ) = split /\|/; if ( exists $exclude_bases{ $base_no } ) { $description =~ s/$exclude_bases{$base_no}{from}/$exclude_bases{$base_no}{to}/g; $_ = join '|', $base_no, $name, $description; } print OUT; } __END__ John -- use Perl; program fulfillment -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/
Re: array within array
On Oct 29, 6:42 am, [EMAIL PROTECTED] (Mike Tran) wrote: Hey all, I'm new with Perl and need help with this simple script. I'm still playing around with the script below to get a feel for Perl. My script below is incomplete and I'm doing an array within an array which is incorrect. Please help. Here's what I want to do; I have to flat files (pipe delimited, export from a database) that I want to parse through and assign variables for each column. Basically, I want to parse through exclude_bases.txt and do: if base_no in exclude_bases.txt equals to base_no in base.txt then search in the description field of base.txt for the string listed in the keyword field in exclude_bases.tx and replace with new_keyword in exclude_bases.txt and write the out put into a new file called new_bases.txt. Any suggestions on how I could accomplish the above task is greatly appreciated. Thanks all. This sounds like a homework assignment, so I won't provide a complete solution, but I will give a few pointers and maybe a little code. Flat Files: base.txt: base_no|name|description 1|test|test desc 10001|test2|test desc 2 10002|test3|test desc 3 exclude_bases.txt: base_no|keyword|new_keyword| 1|test desc|testdesc|0 10001|test desc 2|testdesc2|0 10002|test desc 3|testdesc3|1 Your description of your required output doesn't say what you want to do with the 4th field in the exclude_bases.txt. #!/usr/bin/perl use strict; use warnings; my $exclude_bases = exclude_bases.txt; my $current_base = base.txt; my $output = new_bases.txt; my %exclude_bases; my $exclude_text; my $exbase_no; my $keyword; my $new_keyword; You don't really need most of those and the following global vars. You should define the vars in the smallest scope that they require. open(EXCLUDE,exclude_bases.txt )|| die(Could not open file!); Why didn't you use the $exclude_bases var that you previously defined? You should use the 3 arg form of open and include $! in the die statement which will tell you why it failed. %exclude_bases=EXCLUDE; Why are you slurping the data into a hash? If you use the Data::Dumper module to output that hash, I think you'll find that it's not in the format that you wanted. close(EXCLUDE); my $base_no =; my $name=; my $description=; my $current_base=; my $base_text=; my %bases; open(BASE,base.txt)|| die(Could not open file!); %bases=BASE; close(BASE); See my previous comments. #choping lines and assign variables to base.txt foreach $base_text (%bases) { chop($base_text); use chomp instead of chop ($base_no,$name,$description)=split(/\|/,$base_text); #choping lines and assign variables to exclude_bases.txt foreach $exclude_text (%exclude_bases) { chop($exclude_text); ($exbase_no,$keyword,$new_keyword)=split(/\|/,$base_text); if ($exbase_no=$base_no) { $keyword =~ s/$keyword/$new_keyword/g;} } } ~ Here's how I'd load the hash. my %base; open (my $base, '', 'base.txt') || die base.txt $!; while ($base) { next if /^\s*$/; chomp; my @fields = split /\|/; $base{$fields[0]} = [EMAIL PROTECTED]; } close $base; -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/
RE: array within array
John, That is exactly what I wanted. Thanks for pointing out all those errors for me and your help with the script. Appreciate the prompt respond. Cheers, Mike -Original Message- From: John W.Krahn [mailto:[EMAIL PROTECTED] Sent: Monday, October 29, 2007 1:10 PM To: Perl beginners Subject: Re: array within array On Monday 29 October 2007 06:42, Mike Tran wrote: Hey all, Hello, I'm new with Perl and need help with this simple script. I'm still playing around with the script below to get a feel for Perl. My script below is incomplete and I'm doing an array within an array which is incorrect. Please help. You are not using arrays you are using hashes. Here's what I want to do; I have to flat files (pipe delimited, export from a database) that I want to parse through and assign variables for each column. Basically, I want to parse through exclude_bases.txt and do: if base_no in exclude_bases.txt equals to base_no in base.txt then search in the description field of base.txt for the string listed in the keyword field in exclude_bases.tx and replace with new_keyword in exclude_bases.txt and write the out put into a new file called new_bases.txt. Any suggestions on how I could accomplish the above task is greatly appreciated. Thanks all. Flat Files: base.txt: base_no|name|description 1|test|test desc 10001|test2|test desc 2 10002|test3|test desc 3 exclude_bases.txt: base_no|keyword|new_keyword| 1|test desc|testdesc|0 10001|test desc 2|testdesc2|0 10002|test desc 3|testdesc3|1 #!/usr/bin/perl use strict; use warnings; my $exclude_bases = exclude_bases.txt; my $current_base = base.txt; my $output = new_bases.txt; my %exclude_bases; my $exclude_text; my $exbase_no; my $keyword; my $new_keyword; You should define variables in the smallest possible scope. open(EXCLUDE,exclude_bases.txt )|| die(Could not open file!); You have stored the file name in the $exclude_bases variable above so why do you not use the variable instead? You should include the $! variable in the error message so you know *why* it failed. %exclude_bases=EXCLUDE; You are assigning the list from the file to a hash. The list elements are defined by the value of the $/ variable so here each element of the list is a line from the file. Because you are assigning to a hash the first element is a key and the second element is the value for that key. if any of the keys (odd elements) are the same as a previous key then the old value will be overwritten by the new value and you will lose lines from the file. close(EXCLUDE); my $base_no =; my $name=; my $description=; my $current_base=; my $base_text=; my %bases; open(BASE,base.txt)|| die(Could not open file!); Same as above. %bases=BASE; Same as above. close(BASE); #choping lines and assign variables to base.txt foreach $base_text (%bases) { chop($base_text); You should use chomp() instead of chop(). ($base_no,$name,$description)=split(/\|/,$base_text); #choping lines and assign variables to exclude_bases.txt foreach $exclude_text (%exclude_bases) { chop($exclude_text); Same as above. ($exbase_no,$keyword,$new_keyword)=split(/\|/,$base_text); if ($exbase_no=$base_no) { You are assigning the value of $base_no to the variable $exbase_no. If the value of $base_no is true then the expression is true. You want to use a comparison operator like '==' or 'eq'. $keyword =~ s/$keyword/$new_keyword/g;} Your description said that you wanted to modify 'the description field of base.txt' so that sould be: $description =~ s/$keyword/$new_keyword/g;} } } It looks like you may want something like this: #!/usr/bin/perl use strict; use warnings; my $exclude_bases = 'exclude_bases.txt'; my $current_base = 'base.txt'; my $output= 'new_bases.txt'; open EXCLUDE, '', $exclude_bases or die Could not open '$exclude_bases' $!; my %exclude_bases; while ( EXCLUDE ) { next if $. == 1; # exclude header chomp; my ( $exbase_no, $keyword, $new_keyword ) = split /\|/; $exclude_bases{ $exbase_no } = { from = qr/\Q$keyword/, to = $new_keyword }; } close EXCLUDE; open BASE, '', $current_base or die Could not open '$current_base' $!; open OUT, '', $outputor die Could not open '$output' $!; while ( BASE ) { my ( $base_no, $name, $description ) = split /\|/; if ( exists $exclude_bases{ $base_no } ) { $description =~ s/$exclude_bases{$base_no}{from}/$exclude_bases{$base_no}{to}/g; $_ = join '|', $base_no, $name, $description; } print OUT; } __END__ John -- use Perl; program fulfillment -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/ -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/