swartzieee has asked for the wisdom of the Perl Monks concerning the following question:

I am running a exe within the perl script. Below is the exe when ran in cmd.
Tools4ever Port Ping Utility. Version 2.05 Copyright (c) 2002 Tools4ever bv. All rights reserved. www.tools4ever.com
Host: localhost Connection time: 985 ms Connected host: - Connected port: -1 Error code: 10061 Error text: Error 10061 connecting socket. No connection could be made + because t he target machine actively refused it.
Here is the perl code
my(@PORTS); my($app); @PORTS= qx {C:\\t4ecltbundle\\T4ePortPing localhost 3232}; for(@PORTS){ ($KEY,$VAL)=split(/:/); $HOST=$SITVAL if $KEY =~ /Host/; $CONNTIME=$SITVAL if $KEY =~ /Connection time/; $CONNEDHOST=$SITVAL if $KEY =~ /Connected host/; $CONNEDPORT=$SITVAL if $KEY =~ /Connected port/; $ERRCODE=$SITVAL if $KEY =~ /Error code/; $ERRTEXT=$SITVAL if $KEY =~ /Error text/; } print "$HOST,$CONNTIME"; exit 0;
I want the perl script to basically comma delimit host, connection time, ect. and to delete the first 3 lines of the output

Replies are listed 'Best First'.
Re: format output from a exe within a perl script
by GrandFather (Saint) on Apr 02, 2008 at 02:35 UTC

    You don't actually tell us what the problem is that you see! Most likely the problem is that you haven't used strictures (use strict; use warnings) which would have alerted you to setting $VAL in the split line, but using $SITVAL in the assignment lines.

    /me heads off to apply band aids to his bleeding eyes.


    Perl is environmentally friendly - it saves trees
Re: format output from a exe within a perl script
by jwkrahn (Abbot) on Apr 02, 2008 at 02:34 UTC

    Is there any reason that you can't use the Net::Ping module?

    Perhaps you want something like this:

    open my $PIPE, '-|', 'C:\t4ecltbundle\T4ePortPing', 'localhost', '3232 +' or die "Cannot open pipe from T4ePortPing $!"; my %data; while ( <$PIPE> ) { $data{ host } = $1 if /^Host:\s+(.+)/; $data{ conntime } = $1 if /^Connection time:\s+(.+)/; $data{ connhost } = $1 if /^Connected host:\s+(.+)/; $data{ connport } = $1 if /^Connected port:\s+(.+)/; $data{ errcode } = $1 if /^Error code:\s+(.+)/; $data{ errtext } = $1 if /^Error text:\s+(.+)/; } close $PIPE or warn $! ? "Error closing T4ePortPing pipe: $!" : "Exit status $? from T4ePortPing"; print join ',', @data{ 'host', 'conntime' }; exit 0;
Re: format output from a exe within a perl script
by pc88mxer (Vicar) on Apr 02, 2008 at 02:30 UTC
    I think your script will basically work. All you need to do is change $SITVAL to $VAL, i.e.
    for(@PORTS){ ($KEY,$VAL)=split(/:/); $HOST=$VAL if $KEY =~ /Host/; $CONNTIME=$VAL if $KEY =~ /Connection time/; $CONNEDHOST=$VAL if $KEY =~ /Connected host/; ...
    The only significant thing I would change is to use if/elsif/elsif/... to check for the various key/value pairs:
    if ($KEY =~ /Host/) { $HOST = $VAL; } elsif ($KEY =~ /Connection time/) { $CONNTIME = $VAL; } elsif ($KEY =~ /Connected host/) { ... } ...
    It's safer and more efficient.

    Update: Note that you don't have to explicitly "delete the first three lines" of the output because none of the patterns you are matching against occur in the first three lines. However, if you want to be sure that the first three lines won't enter the for loop, you can eliminate them with:

    splice(@PORTS, 0, 3);

      elsifs are misplaced here for OP wants to know about things in addition to the host.

      Later turns out it was my comment which was misplaced not elsif.

        I'm sorry if it wasn't clear, but I intended to keep the for loop and only replace the separate if statements with a single if/elsif/elsif/... statement, i.e.:
        for (@PORTS) { ($KEY, $VAL) = split(/:/); if ($KEY =~ /Host/) { $HOST = $VAL; } elsif ($KEY =~ /Connection time/) { $CONNTIME = $VAL; } elsif ... }
        Is that what you're referring to?
Re: format output from a exe within a perl script
by kyle (Abbot) on Apr 02, 2008 at 02:47 UTC

    When you have (key, value) pairs, think of a hash. The way you gather up the data for @PORTS is fine, but I've put my variable names in lowercase.

    # remove first three lines shift @ports for 1 .. 3; # remove trailing newline from each line chomp @ports; # turn the lines into key+value pairs my %value_of = map { split /:/, $_, 2 } @ports; while ( my ( $key, $value ) = each %value_of ) { print "$key,$value\n"; } __END__ Error text, Error 10061 connecting socket. No connection could be made + because the target machine actively refused it. Connection time, 985 ms Connected port, -1 Error code, 10061 Connected host, - Host, localhost

    Note that I'm assuming that the "Error text" value was actually one line even though your post has it as two lines with a break in the middle of "the".

    Using shift to remove three lines off the front is sort of lazy. If it were much more, I'd use splice instead. Another way to loop over the keys would be:

    foreach my $key ( keys %value_of ) { print "$key, $value_of{ $key }\n"; }

    Whether you use keys or each, they'll come out in no particular order.

    If you're producing CSV files, you might want to look into Text::CSV rather than do that work yourself.