Try to exit inner loop and start next iteration of outter loop.

Discussion in 'Perl Misc' started by Nene, Dec 12, 2008.

  1. Nene

    Nene Guest

    Hello,

    What I'm trying to do is once my inner loop reaches a count of 5, I
    want it to exit the while statement and go back to the foreach loop.
    But it hangs after it reaches '5' and takes a long time for it go to
    to the second iteration (really large files) of the for foreach loop:

    #!/usr/bin/perl -w
    use strict;

    my @LIST = qw/
    server_1
    server_2
    /;

    my $count = 0;

    FIRST: foreach my $SERVER (@LIST) {

    my $ssh = "ssh $SERVER";
    my $cmd = "perl -ne 'print' /server/directory/file";


    open(SSH, "$ssh $cmd |") || die "ssh: $!";

    print "\n";
    print "Connected to $SERVER\n";


    LINE: while (my $current_line = <SSH>) {
    if ($current_line =~ /Failed at the server/) {
    $count++;
    print "$current_line\n";
    next FIRST if $count == 5;
    }
    }
    }
    Nene, Dec 12, 2008
    #1
    1. Advertising

  2. Nene

    Guest

    Nene <> wrote:
    > Hello,
    >
    > What I'm trying to do is once my inner loop reaches a count of 5, I
    > want it to exit the while statement and go back to the foreach loop.
    > But it hangs after it reaches '5' and takes a long time for it go to
    > to the second iteration (really large files) of the for foreach loop:
    >
    > #!/usr/bin/perl -w
    > use strict;
    >
    > my @LIST = qw/
    > server_1
    > server_2
    > /;
    >
    > my $count = 0;


    Don't you want to reset $count for the next server?

    >
    > FIRST: foreach my $SERVER (@LIST) {
    >
    > my $ssh = "ssh $SERVER";
    > my $cmd = "perl -ne 'print' /server/directory/file";
    >
    > open(SSH, "$ssh $cmd |") || die "ssh: $!";


    For Pete's sake indent your code.

    What is happening is that when
    you re-open SSH, the old handle gets closed. And when a handle from a
    piped open gets closed, it waits for the underlying process to exit. It
    can take a while for your ssh command to decide you stopped listening to it
    and exit.

    You could catch the pid from your open and then kill the pid just before
    you do the "next FIRST". Or you could make the open do a double-fork by
    using the bit of trickery:

    open(SSH, "$ssh $cmd & |") || die "ssh: $!";

    Or you could by-pass the piped-open "magic" by doing the fork and exec
    yourself.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    The costs of publication of this article were defrayed in part by the
    payment of page charges. This article must therefore be hereby marked
    advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
    this fact.
    , Dec 12, 2008
    #2
    1. Advertising

  3. Nene

    J. Gleixner Guest

    wrote:
    > Nene <> wrote:
    >> Hello,
    >>
    >> What I'm trying to do is once my inner loop reaches a count of 5, I
    >> want it to exit the while statement and go back to the foreach loop.
    >> But it hangs after it reaches '5' and takes a long time for it go to
    >> to the second iteration (really large files) of the for foreach loop:
    >>
    >> #!/usr/bin/perl -w
    >> use strict;
    >>
    >> my @LIST = qw/
    >> server_1
    >> server_2
    >> /;
    >>
    >> my $count = 0;

    >
    > Don't you want to reset $count for the next server?
    >
    >> FIRST: foreach my $SERVER (@LIST) {
    >>
    >> my $ssh = "ssh $SERVER";
    >> my $cmd = "perl -ne 'print' /server/directory/file";
    >>
    >> open(SSH, "$ssh $cmd |") || die "ssh: $!";

    >
    > For Pete's sake indent your code.
    >
    > What is happening is that when
    > you re-open SSH, the old handle gets closed. And when a handle from a
    > piped open gets closed, it waits for the underlying process to exit. It
    > can take a while for your ssh command to decide you stopped listening to it
    > and exit.
    >
    > You could catch the pid from your open and then kill the pid just before
    > you do the "next FIRST". Or you could make the open do a double-fork by
    > using the bit of trickery:
    >
    > open(SSH, "$ssh $cmd & |") || die "ssh: $!";
    >
    > Or you could by-pass the piped-open "magic" by doing the fork and exec
    > yourself.


    Or it'd probably be cleaner to simply move the logic of "printing until
    you reach the 5th time /Failed at the server/ happens" to $cmd.

    Also, In the original code, there's no difference between using
    'next FIRST' and simply 'last'. Neither label is needed.

    perldoc -f last
    J. Gleixner, Dec 12, 2008
    #3
  4. Nene <> wrote:

    > #!/usr/bin/perl -w



    The modern, and much better, way is to use lexical warnings
    instead of the command line switch:

    #!/usr/bin/perl
    use warnings;


    --
    Tad McClellan
    email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
    Tad J McClellan, Dec 12, 2008
    #4
  5. Nene <> wrote:
    >Hello,
    >
    >What I'm trying to do is once my inner loop reaches a count of 5, I
    >want it to exit the while statement and go back to the foreach loop.
    >But it hangs after it reaches '5' and takes a long time for it go to
    >to the second iteration (really large files) of the for foreach loop:
    >
    >#!/usr/bin/perl -w
    >use strict;
    >
    >my @LIST = qw/
    >server_1
    >server_2
    >/;
    >
    >my $count = 0;
    >
    >FIRST: foreach my $SERVER (@LIST) {
    >
    >my $ssh = "ssh $SERVER";
    >my $cmd = "perl -ne 'print' /server/directory/file";
    >
    >
    >open(SSH, "$ssh $cmd |") || die "ssh: $!";
    >
    >print "\n";
    >print "Connected to $SERVER\n";
    >
    >
    >LINE: while (my $current_line = <SSH>) {


    Just change this line to

    while (my $current_line = <SSH> and $count < 5) {

    and you can get rid of those stupid labels.

    >if ($current_line =~ /Failed at the server/) {
    >$count++;
    >print "$current_line\n";
    >next FIRST if $count == 5;
    >}
    >}
    >}


    jue
    Jürgen Exner, Dec 12, 2008
    #5
  6. Nene

    Uri Guttman Guest

    >>>>> "JE" == Jürgen Exner <> writes:

    two things:

    JE> Just change this line to

    JE> while (my $current_line = <SSH> and $count < 5) {

    a guideline i use (and stole from peter scott) is to use the word
    booleans (and/or) when doing flow control and the symbolic ones (||, &&)
    when doing expressions. their different precedence works better when
    they are used that way. the above case is an odd one for that rule as
    the binding is better with and (= binds tighter) but it is more of an
    expression. as i said, it is a

    JE> and you can get rid of those stupid labels.

    yes. labels should only be needed in special cases. perl rarely needs
    labels and i barely ever use them. they should only be used when
    nothing else works well.

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Free Perl Training --- http://perlhunter.com/college.html ---------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
    Uri Guttman, Dec 12, 2008
    #6
  7. Jürgen Exner wrote:
    > Nene <> wrote:
    >>
    >> What I'm trying to do is once my inner loop reaches a count of 5, I
    >> want it to exit the while statement and go back to the foreach loop.
    >> But it hangs after it reaches '5' and takes a long time for it go to
    >> to the second iteration (really large files) of the for foreach loop:
    >>
    >> #!/usr/bin/perl -w
    >> use strict;
    >>
    >> my @LIST = qw/
    >> server_1
    >> server_2
    >> /;
    >>
    >> my $count = 0;
    >>
    >> FIRST: foreach my $SERVER (@LIST) {
    >>
    >> my $ssh = "ssh $SERVER";
    >> my $cmd = "perl -ne 'print' /server/directory/file";
    >>
    >>
    >> open(SSH, "$ssh $cmd |") || die "ssh: $!";
    >>
    >> print "\n";
    >> print "Connected to $SERVER\n";
    >>
    >>
    >> LINE: while (my $current_line = <SSH>) {

    >
    > Just change this line to
    >
    > while (my $current_line = <SSH> and $count < 5) {


    You would have to change that to:

    while ( defined( my $current_line = <SSH> ) and $count < 5 ) {

    In case <SSH> returned "0".



    John
    --
    Those people who think they know everything are a great
    annoyance to those of us who do. -- Isaac Asimov
    John W. Krahn, Dec 13, 2008
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Deniz Bahar
    Replies:
    2
    Views:
    463
    Andrey Tarasevich
    Mar 9, 2005
  2. Rudi
    Replies:
    5
    Views:
    4,995
  3. chad
    Replies:
    14
    Views:
    575
    Arnaud Delobelle
    Oct 13, 2010
  4. jay
    Replies:
    1
    Views:
    111
    Austin Ziegler
    Feb 22, 2007
  5. Tad McClellan
    Replies:
    3
    Views:
    138
    Edward Wijaya
    May 13, 2004
Loading...

Share This Page