LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 10-01-2009, 04:51 PM   #1
SuperDude123
Member
 
Registered: Nov 2008
Posts: 158

Rep: Reputation: 30
New to Perl, and its acting funny


Here's my code:
-------------------------
#!/usr/bin/perl

open (IN, "in.txt");
open (OUT, ">out.txt");
my $search1 = 'cup_cakes_sold = ';

while (<IN>){
$found = (index($_, $search1));
if ($found){
$sep = (index($_, ""));
$temp = (substr($_, $sep));
print OUT $temp."4";
}
else{
print OUT $_;
}
}
close IN;
close OUT;
-------------------------



Here's my in.txt file

-------------------------
pancakes = 4



cup_cakes_sold = 3
-------------------------

Here's my out.txt file

-------------------------
pancakes = 4
5
5
5
5cup_cakes_sold = 3
-------------------------

Now what I was trying to do was have out.txt be the same as before, but have my script change the cup_cakes_sold = 3 to cup_cakes_sold = 4. Can someone spot the mistake? This is my first perl script.
 
Old 10-01-2009, 05:51 PM   #2
waltuotinen
LQ Newbie
 
Registered: Oct 2009
Location: Clifton, NJ USA
Posts: 6

Rep: Reputation: 2
Perl acting funny

Perl rarely acts "funny", but it can drive you nuts.

Here are a few tips that may help you get things going the way you want:

$found = (index($_, $search1));
if ($found){ ...

Your conditional logic will execute everytime EXCEPT when the in.txt record contains "cupcakes sold =", because the "index" function returns the offset of the beginning of the string you're looking for in a zero-based fashion. If it's found at the first character, index returns 0 (which is Boolean false). If index doesn't find the string, it returns -1, which is Boolean true.

$sep = (index($_, ""));

This line of code will always assign 0 to $sep, since your asking index to find a null string, which occurs everywhere, hence the first occurence is 0.

Assuming that you just want to change the number of cupcakes from whatever it is to 4, consider this substituting this code instead of all that index and substring stuff:

s/(cup_cakes_sold =).*$/\1 4/;

Also, if you haven't already, buy these 2 O'Reilly books:
Learning Perl
Programming Perl

Best regards,
Walt Uotinen
a.k.a. "The Perl Guy" around my office
 
Old 10-01-2009, 05:56 PM   #3
gzunk
Member
 
Registered: Sep 2006
Posts: 89

Rep: Reputation: 20
I'm not entirely sure what you're trying to do, but your first problem is that the perl function index doesn't return "false" when it doesn't find the value. Therefore your test always succeeds.

The second problem is that you then search for the empty string, which it finds straight away at position 0 (which is correct, the empty string is always the first substring that you can get in a string)

Then you get the subset of the string starting from position 0 (the offset that you've just found) which returns the entire string, then you print that out, appending a "4" at the end. So I would expect your output to look like this:

Code:
pancakes = 4
4
4
4
4cup_cakes_sold = 3
Do you want to add one to the cupcakes, or just change it to 4?
 
Old 10-01-2009, 06:00 PM   #4
smeezekitty
Senior Member
 
Registered: Sep 2009
Location: Washington U.S.
Distribution: M$ Windows / Debian / Ubuntu / DSL / many others
Posts: 2,339

Rep: Reputation: 231Reputation: 231Reputation: 231
Quote:
Originally Posted by waltuotinen View Post
Best regards,
Walt Uotinen
a.k.a. "The Perl Guy" around my office
would look better with a
for example
modfied quote:
"
Best regards,
Walt Uotinen
a.k.a. "The Perl Guy" around my office
"
 
Old 10-01-2009, 06:27 PM   #5
SuperDude123
Member
 
Registered: Nov 2008
Posts: 158

Original Poster
Rep: Reputation: 30
I want to change cup_cakes_sold = 3 to cup_cakes_sold = 4 without all the 4's everywhere. How do I do that?
 
Old 10-01-2009, 07:30 PM   #6
ghostdog74
Senior Member
 
Registered: Aug 2006
Posts: 2,697
Blog Entries: 5

Rep: Reputation: 244Reputation: 244Reputation: 244
Quote:
Originally Posted by SuperDude123 View Post
I want to change cup_cakes_sold = 3 to cup_cakes_sold = 4 without all the 4's everywhere. How do I do that?
here's a pseudocode,try coding yourself:
Code:
if ( found cup_cakes_sold ) {
   split string on "=" #hint : split() function
   change last element of array returned by split to 4
   join string back together # hint: join()
}
 
Old 10-01-2009, 07:31 PM   #7
smeezekitty
Senior Member
 
Registered: Sep 2009
Location: Washington U.S.
Distribution: M$ Windows / Debian / Ubuntu / DSL / many others
Posts: 2,339

Rep: Reputation: 231Reputation: 231Reputation: 231
Quote:
Originally Posted by ghostdog74 View Post
here's a pseudocode,try coding yourself:
Code:
if ( found cup_cakes_sold ) {
   split string on "=" #hint : split() function
   change last element of array returned by split to 4
   join string back together # hint: join()
}
i remember you
you dont just give somebody the code
you will put a trick in it and they figure it out
 
Old 10-01-2009, 10:44 PM   #8
gregorian
Member
 
Registered: Apr 2006
Posts: 509

Rep: Reputation: 34
Quote:
Originally Posted by SuperDude123 View Post
I want to change cup_cakes_sold = 3 to cup_cakes_sold = 4 without all the 4's everywhere. How do I do that?
I hope you're saying that after reading the above posts.
 
Old 10-01-2009, 10:51 PM   #9
SuperDude123
Member
 
Registered: Nov 2008
Posts: 158

Original Poster
Rep: Reputation: 30
Yes, now I have a vague understanding of what I need to do, I just don't know how to do it.

What I want to do is count how many characters there are all the way up to the = sign in the sentence cup_cakes_sold = [some number], and then I need to print those x characters, then tell perl to print " 4" afterwards to do the effect of what I want.

Now if it doesn't see that line in that string of code (correct term??), it is to print it and move on. Could someone tell me what and where I've done wrong with my true/false thing? I realize that its doing the -1 code, however, can someone provide either a solution or a working example so I can see how its supposed to work?
 
Old 10-01-2009, 10:58 PM   #10
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
One begins with Perl putting

Code:
use strict;
use warnings;
in the beginning of his/her script.
 
Old 10-01-2009, 11:02 PM   #11
SuperDude123
Member
 
Registered: Nov 2008
Posts: 158

Original Poster
Rep: Reputation: 30
That just resulted in the following erros:

Global symbol "$found" requires explicit package name at perltest.txt line 17.
Global symbol "$found" requires explicit package name at perltest.txt line 18.
Global symbol "$sep" requires explicit package name at perltest.txt line 19.
Global symbol "$temp" requires explicit package name at perltest.txt line 20.
Global symbol "$sep" requires explicit package name at perltest.txt line 20.
Global symbol "$temp" requires explicit package name at perltest.txt line 21.
Execution of perltest.txt aborted due to compilation errors.
 
Old 10-02-2009, 12:56 AM   #12
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,363

Rep: Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751
You'll find these useful:
http://perldoc.perl.org/
http://www.perlmonks.org/?node=Tutorials

Also, if you have access to those links, I recommend the Perl Cookbook over Programming Perl.


Your 1st task is to sort those issues caused by adding

use strict;
use warnings;

I highly recommend you use those cmds in ALL your Perl progs, even the short temp throwaway ones. They'll save you so much grief in the long run.
 
Old 10-02-2009, 06:58 AM   #13
gzunk
Member
 
Registered: Sep 2006
Posts: 89

Rep: Reputation: 20
Here's a solution, based on waltuotinen's suggestion

Code:
use strict;
use warnings;

open (IN, "in.txt");
open (OUT, ">out.txt");

while (<IN>){
	s/(cup_cakes_sold =).*$/$1 4/;
	print OUT $_;
}

close IN;
close OUT;
The first bit, use strict and use warnings, tells perl that you must defined all variables before using them, and it should flag warnings. This is best practice since it stops you from becoming lazy.

The next two lines open the file descriptors. The while loop goes through the input file line by line.

The we have the magic. We use perl's regular expression handling to perform a substitution on the input line. This basically says, find a line that contains "cup_cakes_sold =" and has multiple things after the equals sign. and substitute it with cup_cakes_sold= 4.

The brackets in the regular expression allow us to save what is matched in the brackets and refer to it as $1. the "." in the regular expression means match any character. The * in the regular expression means match zero or more of the preceding character) in this case ".". the $ means match the end of the line.
 
Old 10-02-2009, 08:02 AM   #14
waltuotinen
LQ Newbie
 
Registered: Oct 2009
Location: Clifton, NJ USA
Posts: 6

Rep: Reputation: 2
Perl acting funny

Try this code:

#!/usr/bin/perl
open (IN, "in.txt");
open (OUT, ">out.txt");
my $search1 = 'cup_cakes_sold = ';
while (<IN>){
if (/(cup_cakes_sold = )(\d+)/) {
$newNum = $2 + 1;
s/(cup_cakes_sold =).*/\1 $newNum/;
}
print OUT $_;
}
close IN;
close OUT;

It will identify any record read in from in.txt that contains
"cup_cakes_sold = " followed by one or more digits, then it will
add 1 to the digit(s) value, and replace the string "cup_cakes_sold = "
with the same string followed by the newly incremented number (i.e., 3 becomes 4, 27 becomes 28, etc.).

Walt
 
Old 10-02-2009, 08:56 PM   #15
gregorian
Member
 
Registered: Apr 2006
Posts: 509

Rep: Reputation: 34
To the OP: I understand you're more interested in understanding what went wrong in your program rather than receiving suggestions for improvement. I've worked on the the suggestions given by waltuotinen (Post #2) and I've changed other things as well. Here's your corrected program with the minimal changes.

Code:
#!/usr/bin/perl

open (IN, "in.txt");
open (OUT, ">out.txt");
my $search1 = 'cup_cakes_sold = ';

while (<IN>){
	$found = index($_, $search1);
	if ($found >= 0){
		$sep = index($_, $search1);
		$temp = substr($_, $sep, length($search1));
		print OUT $temp."4";
	}
	else{
		print OUT $_;
	}
}
close IN;
close OUT;
"print" is your best friend as a new learner. If you're satisfied with this, I suggest you read this thread from the beginning as there's a much simpler way to do this.

perldoc -f <functionname> is the also very useful.

Last edited by gregorian; 10-02-2009 at 09:10 PM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Browser is acting funny inian Linux - Newbie 5 08-04-2009 11:21 AM
nscd acting funny Rufus330Ci Linux - Software 2 04-21-2006 06:51 PM
Is it just me or post acting a little funny? slantoflight General 8 01-03-2006 02:04 PM
sound acting funny madmax04 Fedora 6 10-19-2004 09:20 PM
Gnome acting very funny Stan the caddy Linux - Software 6 09-18-2004 01:57 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 01:10 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration