ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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.
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
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?
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()
}
Distribution: M$ Windows / Debian / Ubuntu / DSL / many others
Posts: 2,339
Rep:
Quote:
Originally Posted by ghostdog74
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
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?
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.
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.
#!/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.).
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.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.