LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Get me out of this while loop( perl regexp) (https://www.linuxquestions.org/questions/programming-9/get-me-out-of-this-while-loop-perl-regexp-790140/)

ashok.g 02-19-2010 03:22 AM

Get me out of this while loop( perl regexp)
 
Guys,
Get me out of the while loop I am using in the code which is:
Code:

#find the no. of occurences of a word in the given line
$a=<STDIN>;
$f=$a;
while($f ne "")
{
        if($f=~/(hi)/)
        {
                #print $f;
                $c++;
        }
$f=$';
}
print "The total no. of ocurrances are $c\n";

Thanks in advance :)

Sergei Steshenko 02-19-2010 03:53 AM

Quote:

Originally Posted by ashok.g (Post 3869129)
Guys,
Get me out of the while loop I am using in the code which is:
Code:

$a=<STDIN>;
$f=$a;
while((defined $f) != " ")
{
        if($f=~/(hi)/)
        {
                print $f;
                $c++;
        }
$f=$';

}

Thanks in advance :)

And why do you think you "deserve" getting out of the loop ? I.e. what diagnostic information do you have to prove that conditions exist to get out of the loop ?

...

For starters, have you actually thought about the validity of this:

Code:

(defined $f) != " "
comparison ? I.e. about types/values of left and right hand sides ?

ashok.g 02-19-2010 04:00 AM

Sergei Steshenko,
I don't really get you what you are trying to say!!

Sergei Steshenko 02-19-2010 04:14 AM

Quote:

Originally Posted by ashok.g (Post 3869159)
Sergei Steshenko,
I don't really get you what you are trying to say!!

Do you compare:
  1. apples to apples ?
  2. apples to oragnes ?
.
After answering the above question try again to answer the question I've asked:

Quote:

For starters, have you actually thought about the validity of this:

Code:

(defined $f) != " "
comparison ? I.e. about types/values of left and right hand sides ?

ashok.g 02-19-2010 06:09 AM

Quote:

Originally Posted by Sergei Steshenko (Post 3869171)
After answering the above question try again to answer the question I've asked:

Ok, I made the changes to the code.... and edited in the main thread. Now tell me wheres my code went wrong????

Sergei Steshenko 02-19-2010 06:22 AM

Quote:

Originally Posted by ashok.g (Post 3869248)
Ok, I made the changes to the code.... and edited in the main thread. Now tell me wheres my code went wrong????

And why should I or anybody else tell you what went wrong ?

The thing that is wrong from the very beginning is lack of debugging skills.

What you are doing is conceptually this:

Code:

while(<condition>)
  {
  <do_something_affecting_the_condition>
  }

You expect <condition> to become false sooner or later, and thus exit the loop, but it apparently it doesn't happen.

So, why should anybody guess why <condition> doesn't go false ? Why don't you make the effort yourself and and print the condition ? I.e. why don't you change your code to become, say:

Code:

while(<condition>)
  {
  <print_the_condition_and_its_internals>
  <do_something_affecting_the_condition>
  }

and/or, if, for example, you definitely know that the loop body shouldn't be executed more than 5 times, then:

Code:

for(my $attempt_number = 0; $attempt_number < 5; $attempt_number++)
#while(<condition>)
  {
  <print_the_condition_and_its_internals>
  <do_something_affecting_the_condition>
  }

?

Then analyze what is printed and fix the problem.

Sergei Steshenko 02-19-2010 06:25 AM

And why don't you use

Code:

use strict;
use warnings;

? I.e. what makes you think your Perl skills are so good you do not need compiler diagnostics ? And what makes you think implementing everything through global (rather than lexical) variables is a good idea ?

ashok.g 02-19-2010 06:35 AM

Quote:

Originally Posted by Sergei Steshenko (Post 3869262)
And why should I or anybody else tell you what went wrong ?

I think this forum is for sharing the views, helping others in getting out of their problems(technical n non-technical if possible),etc. Isn't it?
Quote:

Originally Posted by Sergei Steshenko (Post 3869262)
The thing that is wrong from the very beginning is lack of debugging skills.

Who said I didn't used any debugging skills?
For your kind information here is the code where I used some debugging skills
Code:

#print $f;
Quote:

Originally Posted by Sergei Steshenko (Post 3869262)
What you are doing is conceptually this:

Code:

while(<condition>)
  {
  <do_something_affecting_the_condition>
  }

You expect <condition> to become false sooner or later, and thus exit the loop, but it apparently it doesn't happen.

So, why should anybody guess why <condition> doesn't go false ? Why don't you make the effort yourself and and print the condition ? I.e. why don't you change your code to become, say:

Code:

while(<condition>)
  {
  <print_the_condition_and_its_internals>
  <do_something_affecting_the_condition>
  }

and/or, if, for example, you definitely know that the loop body shouldn't be executed more than 5 times, then:

Code:

for(my $attempt_number = 0; $attempt_number < 5; $attempt_number++)
#while(<condition>)
  {
  <print_the_condition_and_its_internals>
  <do_something_affecting_the_condition>
  }

?

Then analyze what is printed and fix the problem.

I think its better to solve the problem rather than teaching the entire control statements like while, for,etc., which I had already know if you can.

Sergei Steshenko 02-19-2010 06:41 AM

Quote:

Originally Posted by ashok.g (Post 3869277)
I think this forum is for sharing the views, helping others in getting out of their problems(technical n non-technical if possible),etc. Isn't it?

Who said I didn't used any debugging skills?
For your kind information here is the code where I used some debugging skills
Code:

#print $f;
I think its better to solve the problem rather than teaching the entire control statements like while, for,etc., which I had already know if you can.

I do not see the printouts. And I do now want to guess. And I do not know what your input data is.

Every bug reporting guidelines demand publishing log files/screen output when they are available. In your case screen output can definitely be made available.

ashok.g 02-19-2010 06:54 AM

Quote:

Originally Posted by Sergei Steshenko (Post 3869286)
I do not see the printouts. And I do now want to guess. And I do not know what your input data is.

Every bug reporting guidelines demand publishing log files/screen output when they are available. In your case screen output can definitely be made available.

Here you go!
I am presenting in front of you the entire input/output and source files.
Firstly the source file:
Code:

#find the no. of occurences of a word in the given line
$a=<STDIN>;
$f=$a;
while($f ne "")
{
        if($f=~/(hi)/)
        {
                print $f;
                $c++;
        }
$f=$';
}
print "The total no. of ocurrances are $c\n";

Input/Output:
Code:

[Ashok@station130 My Work]$ perl temp.pl
hi hhhhi hihihi hihi
hi hhhhi hihihi hihi
 hhhhi hihihi hihi
 hihihi hihi
hihi hihi
hi hihi
 hihi
hi

Observe that in the end I am not able to return to my prompt again.Its running an infinite loop there.
Now I think this information is more than enough for you and its your turn now.

Sergei Steshenko 02-19-2010 07:03 AM

Quote:

Originally Posted by ashok.g (Post 3869304)
Here you go!
I am presenting in front of you the entire input/output and source files.
Firstly the source file:
Code:

#find the no. of occurences of a word in the given line
$a=<STDIN>;
$f=$a;
while($f ne "")
{
        if($f=~/(hi)/)
        {
                print $f;
                $c++;
        }
$f=$';
}
print "The total no. of ocurrances are $c\n";

Input/Output:
Code:

[Ashok@station130 My Work]$ perl temp.pl
hi hhhhi hihihi hihi
hi hhhhi hihihi hihi
 hhhhi hihihi hihi
 hihihi hihi
hihi hihi
hi hihi
 hihi
hi

Observe that in the end I am not able to return to my prompt again.Its running an infinite loop there.
Now I think this information is more than enough for you and its your turn now.

No, the information is not sufficient (but I think I know what the problem is).

As I said, the problem is debug skills, and, in this case, poor way to display a variable with text contents.

The point is that text can also contain whitespaces, and you made no effort to implement your print statements in a manner than shows whitespaces.

So, for starters, assuming that your input data does not contain '|' character, please do the following:
  1. read 'perldoc -f warn'
  2. comment out 'print $f;'
  3. in the very beginning of the loop body place: 'warn "|\$f|=|$f|";'

and publish the screen output again.

druuna 02-19-2010 07:13 AM

Hi,

Here's a solution for your problem, based on your original code:
Code:

#!/usr/bin/perl

use strict ;
use warnings ;

my $a ;
my $c = '0';
my $f ;

$a = <STDIN> ;
$f = $a ;
while ( $f ne "" ) {
  chomp $f;
  if ( $f =~ /(hi)/ ) {
      $c++ ;
  }
  $f = $' ;
}
print "The total no. of ocurrances are $c\n" ;

exit 0;

I agree with Sergei Steshenko that you do need to give the appropriate information (which you partially did).

It is up to you to figure out why the above code works and yours did not (you do want to learn something, don't you?).

Anyway, hope this helps.

Sergei Steshenko 02-19-2010 07:16 AM

Quote:

Originally Posted by druuna (Post 3869330)
Hi,

Here's a solution for your problem, based on your original code:
Code:

#!/usr/bin/perl

use strict ;
use warnings ;

my $a ;
my $c = '0';
my $f ;

$a = <STDIN> ;
$f = $a ;
while ( $f ne "" ) {
  chomp $f;
  if ( $f =~ /(hi)/ ) {
      $c++ ;
  }
  $f = $' ;
}
print "The total no. of ocurrances are $c\n" ;

exit 0;

I agree with Sergei Steshenko that you do need to give the appropriate information (which you partially did).

It is up to you to figure out why the above code works and yours did not (you do want to learn something, don't you?).

Anyway, hope this helps.


Arrrrgh, you spoiled such a nice party :).

druuna 02-19-2010 07:22 AM

@Sergei Steshenko: LOL.

I do hope that the OP doesn't just copy/paste that line, but understands why this needs to be implemented this way. But like I stated before, that is up to him. I also hope that it is clear to the OP why strict/warnings are needed in the code.

ashok.g 02-19-2010 07:36 AM

I am really enjoying this guys.

I think your code really works for only some inputs.
But what about this input?
Code:

[Ashok@station130 My Work]$ perl temp.pl
not getting hi here

Its again running an infinite loop for YOUR code. You debug your code now.

ashok.g 02-19-2010 08:06 AM

K guys,
I'm I am calling the day off. I will catch you surely tomorrow.
Hope you will debug your code.
Happy posting :)

ghostdog74 02-19-2010 08:44 AM

Quote:

Originally Posted by ashok.g (Post 3869129)
Guys,
Get me out of the while loop I am using in the code which is:
Code:

#find the no. of occurences of a word in the given line
$a=<STDIN>;
$f=$a;
while($f ne "")
{
        if($f=~/(hi)/)
        {
                #print $f;
                $c++;
        }
$f=$';
}
print "The total no. of ocurrances are $c\n";

Thanks in advance :)

see perldoc -q count.
Code:

while(<>){
    $count = () = $_ =~ /hi/g;
    print "count: $count\n";
}


druuna 02-19-2010 10:18 AM

Hi,

@ghostdog74: One of the things the OP does not comprehend is the way STDIN works and how to implement this in a perl program. He will keep complaining about "being stuck in a loop", which is also "true" for your short and elegant solution.

But without a clear description of what it is he tries to accomplish (is perl a must, is there always 1 line of input from STDIN or could there be more, is STDIN actually needed) solving his problem for him (it looks like learning is not on his agenda) is going to be problematic.

Aizenmyou 02-19-2010 02:22 PM

Quote:

Originally Posted by ashok.g (Post 3869388)
I'm I am calling the day off. I will catch you surely tomorrow.
Hope you will debug your code.
Happy posting :)

I'm sorry but that is so "WTF".

Sergei Steshenko 02-19-2010 03:45 PM

Quote:

Originally Posted by ashok.g (Post 3869353)
I am really enjoying this guys.

I think your code really works for only some inputs.
But what about this input?
Code:

[Ashok@station130 My Work]$ perl temp.pl
not getting hi here

Its again running an infinite loop for YOUR code. You debug your code now.

This is you who has to debug your code.

This is your duty to verify the while loop condition.

You shouldn't have just taken the code published by others (an I only published a statement supposed to help debugging), you should have analyzed the root cause and should have corrected it.

This is not your first thread regarding your Perl problems, and to me it looks like you repeat making the same mistakes.

This is you who gave no explanation regarding

Quote:

not getting hi here
- is it your input from keyboard ? If yes, why do you think your code is supposed to work ? I.e. based on what exactly statements in Perl documentation is your code supposed to work for such input ?

ghostdog74 02-19-2010 08:01 PM

Quote:

Originally Posted by druuna (Post 3869520)
Hi,

@ghostdog74: One of the things the OP does not comprehend is the way STDIN works and how to implement this in a perl program. He will keep complaining about "being stuck in a loop", which is also "true" for your short and elegant solution.

don't understand. if he wants to use STDIN,
Code:

echo "hi there hi hi" | perl myscript.pl
Also, i have directed OP to see the perldoc. That's where he can find how to count words. Its all from perldoc.

ashok.g 02-20-2010 12:12 AM

Hi ghostdog74,
Quote:

Originally Posted by ghostdog74 (Post 3869429)
see perldoc -q count.

Thanks for your suggestion.
Quote:

Originally Posted by druuna (Post 3869520)
@ghostdog74: One of the things the OP does not comprehend is the way STDIN works and how to implement this in a perl program. He will keep complaining about "being stuck in a loop", which is also "true" for your short and elegant solution.

I think <STDIN> is used to get the entire line the user entered along with the last line. So, to remove that last line we generally use chomp.This is what I know about <STDIN>. If this is not correct I request you to suggest me some documents as ghostdog74 did.
Quote:

Originally Posted by Sergei Steshenko (Post 3869800)
This is not your first thread regarding your Perl problems, and to me it looks like you repeat making the same mistakes.

Sergei Steshenko, If I'm not rude could you please tell me what made you think I'm repeating the same mistakes.

Also, I request all you guys to suggest me documents in learning perl effectively.

Sergei Steshenko 02-20-2010 01:29 AM

Quote:

Originally Posted by ashok.g (Post 3870092)
...
Also, I request all you guys to suggest me documents in learning perl effectively.

Your problem is not no knowing Perl, as I wrote, your problem is lack of basic debugging skills. Getting out of endless 'while' loop with condition as simple as

Code:

while($s ne '')
is trivial in any language - one has to analyze the value $s - end of story.

ashok.g 02-20-2010 02:48 AM

Quote:

Originally Posted by Sergei Steshenko (Post 3870145)
Getting out of endless 'while' loop with condition as simple as

Code:

while($s ne '')
is trivial in any language - one has to analyze the value $s - end of story.

But i'm not getting out of the while loop using the code which you specified either.
Could you please check your code with the input as "hiiiiiii"?

druuna 02-20-2010 04:33 AM

Hi ashok.g,

Let's try to get this back on track again.......

I'm curious about something: Have you played with and do you understand the following example (I used ghostdog74's example [post #17], because it is the most elegant and simple):
Code:

#!/usr/bin/perl

use strict ;
use warnings ;

my $count ;

while ( <> ) {
  $count = () = $_ =~ /hi/g ;
  print "count: $count\n" ;
}

I am not talking about the count part or the condition part (although those are important for other reasons), but why you do not get your prompt back and the script keeps waiting for input.

You mention the following in one of your replies:
Quote:

I think <STDIN> is used to get the entire line the user entered along with the last line. So, to remove that last line we generally use chomp.This is what I know about <STDIN>.
STDIN takes input form standard in (in your case you use the keyboard but it could also be a pipe). It keeps waiting for input until it gets an EOF (end of file character).
A carriage return (enter or return if you will, also represented in linux as \n or \r) is not an EOF, it is seen as part of the input. Using chomp will not help. Chomp takes off the end character of a specified string ONLY if that character is a RETURN (Enter).

If you do the following: echo "not getting hi here" | ./hi.counter.pl (hi.counter.pl being the example I posted a few lines back):
the output will be: count: 1
And you will have your prompt back.

If you do this: ./hi.counter.pl
And enter not getting hi here from the keyboard, you will get count: 1 but you will not get your prompt back.

The first one also echo's an EOF and the script (be it perl, bash, awk or whatever) knows there is no more input coming from STDIN and it can continue.
The second example does not echo an EOF and STDIN keeps waiting for input.

You can enter an EOF from the keyboard by pressing ctrl-d. This will tell STDIN that no more input is comming and the script can continue (STDIN can take multiple lines).

STDIN, STDERR and STDOUT are not perl specific.

A few URL's about this subject:
(perl) Reading Input from Standard Input
(wiki) Standard streams
(shell) stdin, stdout, stderr

Hope this finally clears things up a bit.

ashok.g 02-20-2010 05:14 AM

Hi druuna,
Thanks for your post #25. I really understood the program which ghostdog74 quoted in the post #17 with the concept I have about EOF, EOL and STDIN. But your explanation for them is very neat and clean. :)

Coming back to the line which I had written in the code,
Code:

while ( $f ne "" )
or the line suggested by Sergei Steshenko in one of his replies
Code:

while ( $f ne '')
(I think both conditions will return the same value in this context)
In this line we are not expecting any EOL character rather than we are expecting the condition to be failed. Isn't it?
But as you said we are not echoing any EOL using <STDIN>, then it must wait for the input( You also specified this point in your reply :"The second example does not echo an EOL and STDIN keeps waiting for input") rather than going for an infinite loop( please give any prrint statement like print ("------\n")inside while loop then you can see its goiing infinite loop).

druuna 02-20-2010 05:43 AM

Hi,

Stupid me, I mixed up EOL and EOF in my previous reply (already fixed it).

Please have another look.

Sorry for that!!

ashok.g 02-20-2010 05:48 AM

But what about my post, #26

druuna 02-20-2010 06:10 AM

Hi again,

The reason I used ghostdog74 example and not your initial script is 'cause your script is basically flawed.

This $a = <STDIN> ; will set up the STDIN 'rules' (waiting for a EOF, which is essentially a loop). After that you create another loop (the while ( $f ne '' ) { part), within the first loop. The action part of the while construct (if ....) is caught between 2 loops.

You have a valid script if you re-write your original script to this:
Code:

#!/usr/bin/perl

use strict ;
use warnings ;

my $c = '0' ;

while ( <STDIN> ) {
  if ( $_ =~ /hi/ ) {
      $c++ ;
  }
}
print "The total no. of ocurrances are $c\n" ;

Now you have 1 loop (reading from STDIN) and the stdin rules apply.

echo "not getting hi here" | ./hi.counter.2.pl
Output: The total no. of ocurrances are 1
And you have your prompt back.

Or: ./hi.counter.2.pl
Enter text from keyboard: not getting hi here (with or without enter/return [=EOL!!])
Enter EOF char to stop the loop: ctrl-d
Output will be:
The total no. of ocurrances are 1
or
not getting hi hereThe total no. of ocurrances are 1
depending on the enter/return you did (output 1) or did not (output 2) press. In both cases your prompt is back.

Hope this helps.

ashok.g 02-20-2010 06:35 AM

I'm really exhausted today with my work and these posts.
Druuna,
Your last code is working fine with respective to the control loops and all other stuff but it actually doesn't serving the main functionality, i.e., counting the no.of occurances of a word.
(please give multiple "hi"s in multiple lines like
hi hi hi
hiiiiiiiiiiiii
hhhhhhhhhhi
)
It's giving the worng output even after I gave /g in matching there.

druuna 02-20-2010 06:51 AM

Hi,

This is one solution:
Code:

#!/usr/bin/perl

use strict ;
use warnings ;

my $count = 0 ;

while ( <STDIN> ) {
  for ( split ) {        # break up everything into single words
      if ( $_ =~ /hi/ ) {  # only increase counter if word equals hi
        $count++ ;
      }
  }
}
print "Counted hi: $count time(s).\n" ;

I introduced a new perl function: split

Have a look here for an explanation:
(perl tutorial) split
(perldoc) split
(perlmeme) Using the Perl split() function

Hope this helps.

ashok.g 02-21-2010 11:40 PM

Hi druuna,
Again you are coming with other solution than the one I used.
Actually I implemented the same in different ways. But, I took it as a challenge to achieve this code only with the help of perl regular expression's special variables($&,$',$`) and some control statements(like while,for,etc.,..). That is why I'm more particular about this post.

Hope you understood my concern.
Thank You!


All times are GMT -5. The time now is 05:14 PM.