Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

This should be simple

by steppnav (Initiate)
on Jun 29, 2022 at 23:24 UTC ( #11145179=perlquestion: print w/replies, xml ) Need Help??

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

Very recent perl on Cygwin

Summary of my perl5 (revision 5 version 32 subversion 1) configuration +: Platform: osname=cygwin osvers=3.2.0(0.34053) archname=x86_64-cygwin-threads-multi uname='cygwin_nt-10.0 cygwinpro 3.2.0(0.34053) 2021-03-29 08:42 x8 +6_64 cygwin '

Why doesn't this give just the ip address without a trailing ')'??

#!/usr/bin/perl my $ip = "csteppfw pts/0 2022-06-27 15:53 (192.168.5.100)"; $ip =~ s/.*?(\d+\.\d+\.\d+\.\d+).*?/\1/; ## $line =~ s/.*$ip//; print "$ip\n"; -------------------- $ bin/test 192.168.5.100)

Replies are listed 'Best First'.
Re: This should be simple (updated)
by AnomalousMonk (Bishop) on Jun 30, 2022 at 02:30 UTC

    Regexp::Common is useful for patterns like dotted decimal IPv4 addresses. The following gives you the leftmost such address. If you want to be sure to get the address between the parentheses, use literal parens as positive lookaround anchors.

    Win8 Strawberry 5.30.3.1 (64) Wed 06/29/2022 21:31:05 C:\@Work\Perl\monks >perl use strict; use warnings; use Regexp::Common qw(net); my $ip = 'csteppfw pts/0 2022-06-27 15:53 (192.168.5.100)'; ($ip) = $ip =~ m{ (?<! \d) $RE{net}{IPv4} (?! \d) }xmsg; print "'$ip' \n"; ^Z '192.168.5.100'

    Update: If for some reason you want to roll your own IPv4 regex ("I can't download modules!" — but see Yes, even you can use CPAN):

    Win8 Strawberry 5.8.9.5 (32) Wed 06/29/2022 23:13:52 C:\@Work\Perl\monks >perl use strict; use warnings; # same as $RE{net}{IPv4} dotted decimal my $octet = qr{ 25 [0-5] | 2 [0-4] \d | [01]? \d \d? }xms; my $rx_ipv4 = qr{ (?> $octet (?: [.] $octet){3}) }xms; my $ip = 'csteppfw pts/0 2022-06-27 15:53 (192.168.5.100)'; ($ip) = $ip =~ m{ (?<! \d) $rx_ipv4 (?! \d) }xmsg; print "'$ip' \n"; ^Z '192.168.5.100'


    Give a man a fish:  <%-{-{-{-<

      Good input all! Thanks. The comment about stuff not being anchored help me understand why the "throw away the last part of the line" part of the match didn't get the paren following the naive regex pattern (I don't care if it is a valid IP). I had put that '?' non-greedy flag on and with .* an empty string matched. All I had to do was anchor the end with '$'.

      That assignement into a list with a capturing /.../ match thing was very interesting. I'm using a goofy while loop to repeatedly capture and the rip off the IP from lines until there is no matching IP pattern, then move on to the next line (while (<>). That assignement using the match looks like I could use it with an array variable on the left and a 'g' on the match to capture all the matching IP's on a given line. I'll try that after coffee.

      Thanks again.

        ... using a ... while loop to repeatedly capture and the rip off the IP from lines until there is no matching IP pattern ... use it with an array variable on the left and a 'g' on the match to capture all the matching IP's on a given line.

        Exactly right.


        Give a man a fish:  <%-{-{-{-<

Re: This should be simple
by Your Mother (Archbishop) on Jun 29, 2022 at 23:46 UTC

    Try this and give it a bit of consideration and you’ll have your answer, I think–

    my $ip = "csteppfw pts/0 2022-06-27 15:53 (192.168.5.100)"; my ( $match ) = $ip =~ /.*?(\d+\.\d+\.\d+\.\d+).*?/; print "$match\n";
Re: This should be simple
by LanX (Sage) on Jun 30, 2022 at 00:05 UTC
    Your Mother is spot on, just match instead of trying to replace.

    Regarding your core question, you have multiple problems

    • you don't anchor the pattern between literal parens \( ... \)
    • your trailing quantifier is non-greedy .*? and is satisfied after matching 0 characters, i.e. the rest is not replaced
    • this could also have been fixed by additionally anchoring on ^start and end$ to really replace the whole string

    Anyway here a demo that works

    C:\tmp>perl my $ip = "csteppfw pts/0 2022-06-27 15:53 (192.168.5.100)"; $ip =~ s/.*\((\d+\.\d+\.\d+\.\d+)\).*/\1/; print $ip; __END__ 192.168.5.100 C:\tmp>

    But still, simply matching is better.

    C:\tmp>perl my $ip = "csteppfw pts/0 2022-06-27 15:53 (192.168.5.100)"; print $1 if $ip =~ /\((\d+\.\d+\.\d+\.\d+)\)/; __END__ 192.168.5.100 C:\tmp>

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11145179]
Approved by LanX
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (3)
As of 2022-08-19 20:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?