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

Dear monks, I was playing around with the Net::Jabber module when I cam e across the following code in XML::Stream (line 819) module.
my($host,$port) = ($ENV{"http_proxy"} =~ /^(\S+)\:(\d+)$/);
I do not understand the above code. Both "host" and "port" are undefined after the above statement is executed. http_proxy is set to "http://my.proxy.example.com:8080/". I am trying to understand what is expected behavior of above code. And why is "host" and "port" not being set? I have not encountered this syntax before. Thanks, Anand

Replies are listed 'Best First'.
Re: need help understanding perl syntax
by phaylon (Curate) on Jun 16, 2006 at 15:17 UTC
    I'd guess you have to kill that trailing slash on your http_proxy, otherwise (\d+)$ won't work.

    hth, p

    Update: As an addition to socketdave's solution and because it's fun to pass around people's focus, the slash can of course also just be optional:

    m[^(\S+)\:(\d+)/?$]

    Ordinary morality is for ordinary people. -- Aleister Crowley
Re: need help understanding perl syntax
by socketdave (Curate) on Jun 16, 2006 at 15:08 UTC
    $ENV{"http_proxy"} retrieves the environment variable http_proxy, splits it into a non-whitespace section and a numeric section separated by a ':'. These sections are assigned to $host and $port.

    Just a guess, but have you tried upper-casing "HTTP_PROXY" in the code?

    UPDATE: See phaylon's response below. I didn't spot that trailing slash in your data. If your data will always have the slash, you can do:my($host,$port) = ($ENV{"http_proxy"} =~ /^(\S+)\:(\d+)\/$/); to account for it.
Re: need help understanding perl syntax
by sgifford (Prior) on Jun 16, 2006 at 15:41 UTC
    What that code says is "Match the environment variable http_proxy against the a regular expression with two captures, and return the two captures". undef in both of these variables implies that the variable didn't match the regular expression.

    The regular expression is "start of string, followed by one or more non-space characters (captured), followed by a colon, followed by 1 or more digit characters (captured), followed by end of string". The string you give doesn't match that, because of the trailing slash.

Re: need help understanding perl syntax
by mikeock (Hermit) on Jun 16, 2006 at 15:17 UTC
    Try Upper casing HTTP_PROXY.. Also I dont know if the quotes are required.

    My sig Sucks!
Re: need help understanding perl syntax
by Anonymous Monk on Jun 17, 2006 at 10:34 UTC
    Thank you all very much. The problem was resolved after I removed the trailing '/' in the http_proxy environment variable. I cant believe I missed something this obvious.

    <aside> This is the first time I am encountering the "match-and-assign-in-a-single-statement" syntax.

    my($host, $port) = ( $ENV{"http_proxy"} =~ /^(\S+)\:(\d+)$/ );
    I usually code like this:
    if( $ENV{"http_proxy"} =~ /^(\S+)\:(\d+)$/ ) { ($host, $port) = ($1, $2); }
    Which syntax is better/preferable? Is it more a style issue and either syntax is fine?
    </aside>

    Thanks,
    Anand

      That depends (as always). The difference is, yours is "better" because it just does more. It makes sure to only do something if the environment variable has a proper value. If you "feel" you'd have to do something if the value is incorrect, like emitting a warning or an error, the if version is great. If you have built or validated your string beforehand, or got it out of a data store where only valid strings are, you can just use the assignment. If you're not sure that you'll remember what it does (because you're not using it very often, for example) just add a comment that explains it. When in doubt, I'd recommend your version though.

      hth, p

      Ordinary morality is for ordinary people. -- Aleister Crowley
        You can have both:
        if ( ($host, $port) = ( $ENV{"http_proxy"} =~ /^(\S+)\:(\d+)$/ ) ) { print $host, "/", $port; } else { print "warning"; }


        holli, /regexed monk/