?
Solved

parsing input from endless input?

Posted on 2003-02-25
11
Medium Priority
?
148 Views
Last Modified: 2012-08-13
Im making a perl program that is running as a subprogram of something else,
the stdin and stdout for this perl program are directed towards the perl's parent program. So stdin/out is actually coming from the parent.

The problem is is that I need to get a bunch of lines of input and then process them, but the way the system is set up, I can't do "@all = <STDIN>" because the stdin never has an EOF signal, if I DO do it, it will just wait for ever thinking more input will be coming...

Is there a way to read in until the program isn't being passed anything more, that is, check that stdin isn't returning anything more.

I would like to know because, the input that comes in could vary in length, so I can't just read in 'X' times and stop.


Thanks
0
Comment
Question by:ServerOverflow
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
  • 2
  • +4
11 Comments
 

Author Comment

by:ServerOverflow
ID: 8021301
Perhaps is there a way to read stdin and then if nothing happens after (say 5 seconds) stop reading?
0
 
LVL 26

Expert Comment

by:wilcoxon
ID: 8021378
You should be able to use $SIG{ALARM} to break out of reading from <IN>.  You should be able to find more info in perldoc (or on perldoc.com) or in Programming Perl.
0
 
LVL 2

Accepted Solution

by:
blinkie23 earned 480 total points
ID: 8023065
try this.  this script will exit after 5 seconds if no input is received on STDIN.  if input is received, it will exit if no input is received for 2 seconds at any point.  the 2 second timer restarts each time input is received.  modify it to your liking.

#!/usr/bin/perl

$SIG{ALRM} = sub { break; };

alarm 5;
while(<STDIN>){
    alarm 2;
    print;
}
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:ServerOverflow
ID: 8026911
Hmmm ok, blinkie that stops just like you said, very nice, but how can I get it to just exit the loop and continue on with the rest of the code?

right now it exits the program and I've tried changing the SIGALRM line to last, but no matter what it just exits... very annoying...


Thanks...
0
 
LVL 2

Expert Comment

by:blinkie23
ID: 8027299
that is annoying... but if i put code after my while statement, it executes it normally for either alarm signal that is caught.  i'm not sure why it works for me, and not you.  i am on a unix platform, maybe you're on a windows one?  ... can you troubleshoot the problem out more?  confirm that both the breaks exit the program, or just one of the breaks cause an exit.
0
 
LVL 1

Expert Comment

by:mikezone
ID: 8027528

Perhaps this:

  #! /usr/bin/perl

  my @processed_data;
  my @unprocessed_data;

  $SIG{ ALRM } = sub {
    process_data();
    alarm( 2 );
  };

  alarm( 2 );
  while( <STDIN> ) {
    push @unprocessed_data, $_;
  }

  sub process_data {
    @processed_data = (); # Remove this line if you don't want incremental processing.
    foreach (@unprocessed_data) {
      my $processed_data = "> $_";
      push @processed_data, $processed_data;
    }
    @unprocessed_data = ();

    # ===== DO SOMETHING WITH PROCESSED DATA
    open FILE, ">>processed.txt";
    print FILE @processed_data;
    close FILE;
  }

What this does:

The alarm is set just before the program gets into the while loop and starts reading data and sending it to a stack (@unprocessed_data), which holds the data for processing. When the alarm goes off, the program's flow of control switches to the alarm handler, which processes the data, and transfers the processed data to another stack. It also empties the unprocessed data stack. The neat part is that the signal handler resets the alarm, so it will happen in timely increments.

To do what you mentioned that you wanted to do, you might try to set a flag:

  #! /usr/bin/perl

  my $exit = undef;
  $SIG{ ALRM } = sub { $exit = 1 };

  alarm( 5 );
  while( <STDIN> && ! $exit ) {
    print;
  }

It may be that the last() is confused about what scoping it's in. Labels may fix this, but flags are, IMHO, more readable.

  #! /usr/bin/perl

  $SIG{ ALRM } = sub { last INPUT_LOOP; }

  INPUT_LOOP: while( <STDIN> ) {
    print;
  }

Hope this helps,

- m.
0
 
LVL 2

Expert Comment

by:perldork
ID: 8027724
You could also try using eval to do the equivalent of a try/catch:


eval {
    alarm(3);
    $SIG{ALRM} = sub { die "timeout\n" };

    while(1) {
        print "hi\n";
        sleep(2);
    }
};

if ($@ =~ /timeout/) {
    print "Timed out!\n";
} else {
    die $@;
}

0
 
LVL 2

Expert Comment

by:perldork
ID: 8027738
Sorry .. should have been this:

$|++;

eval {
    alarm(3);
    $SIG{ALRM} = sub { die "timeout\n" };

    while(1) {
        print "hi\n";
        sleep(2);
    }
};

if ($@ =~ /timeout/) {
    print "Timed out!\n";
} elsif (defined $@) {
    die $@;
}
0
 
LVL 2

Expert Comment

by:Itatsumaki
ID: 8028899
The solutions posted above are pretty good.  Just as a dumb question: any reason why the parent program can't pass in some indicator that it's done giving data?  That would be a bit cleaner than waiting a certain number of seconds, I think.

Just an idea,
Tats
0
 
LVL 11

Expert Comment

by:kblack05
ID: 8029550
Use next instead of die.
if ($@ =~ /timeout/) {
   print "Timed out!\n";
} elsif (defined $@) {
   next "";
}


~Kelly W. Black
0
 

Author Comment

by:ServerOverflow
ID: 8029558
Ok thanks guys, all of them were good,
blinkie was the first to answer and that worked after putting the whole thing inside an eval{} expression so im giving it to him ;)


btw. I didnt make the parent program and I dont have source code so I can't change the way it sends its children messages, pretty lame I know, gotta love programmers that don't think ahead...


Thanks to EVERYONE!
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Email validation in proper way is  very important validation required in any web pages. This code is self explainable except that Regular Expression which I used for pattern matching. I originally published as a thread on my website : http://www…
There are many situations when we need to display the data in sorted order. For example: Student details by name or by rank or by total marks etc. If you are working on data driven based projects then you will use sorting techniques very frequently.…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Six Sigma Control Plans
Suggested Courses

765 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question