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

Sorry, it's been a long day, and my brain is cramping.
#!/usr/bin/perl # # use strict; use warnings; my $time = "123456.745768"; my $time2 = "123456.745768"; $time =~ s/^(\d{2})(\d{2})(\d{2})\.(\d{2})\d{4}/$1:$2:$3.$4/; $time2 =~ s/^(\d{2})(\d{2})(\d{2})\.(\d{2})/$1:$2:$3.$4/; print "$time\n"; print "$time2\n";
gives me
12:34:56.74 12:34:56.745768
Shouldn't the substitution of $time2 work? IE -- see two digits after the '.' and then leave it at that?

I even tried
$time2 =~ s/^(\d{2})(\d{2})(\d{2})\.(\d{2}).+?/$1:$2:$3.$4/;
but got the same (bad) results.

Replies are listed 'Best First'.
Re: A would-be simple substitution...
by Roger (Parson) on Mar 02, 2004 at 07:33 UTC
    Your $time2 is only replacing the bits that "matched", the parts unmatched are not touched.

    And also in your other attempt:
    $time2 =~ s/^(\d{2})(\d{2})(\d{2})\.(\d{2}).*?$/$1:$2:$3.$4/; # ^ # add anchor point

Re: A would-be simple substitution...
by Tomte (Priest) on Mar 02, 2004 at 07:40 UTC

    Shouldn't the substitution of $time2 work? IE -- see two digits after the '.' and then leave it at that?

    No ;-), because you are substituting the matching part, and the trailing digits do not match, they are therefore left alone.

    I even tried
    $time2 =~ s/^(\d{2})(\d{2})(\d{2})\.(\d{2}).+?/$1:$2:$3.$4/;
    but got the same (bad) results.

    I didn't:

    #!/usr/bin/perl # # use strict; use warnings; my $time2 = "123456.745768"; $time2 =~ s/^(\d{2})(\d{2})(\d{2})\.(\d{2}).+?/$1:$2:$3.$4/; print "$time2\n"; __END__ 12:34:56.74768
    Notice the missing five? .+? is non greedy and matches only what it has to, in this case one single character.

    take away the ?, and it does, what you want; I'd change the . (dot) to \d and the + to a * though, resulting in

    s/^(\d{2})(\d{2})(\d{2})\.(\d{2})\d*/$1:$2:$3.$4/;

    regards,
    tomte


    Hlade's Law:

    If you have a difficult task, give it to a lazy person --
    they will find an easier way to do it.

      See -- told you it was a long day. :) A cold AND jet lag are a losing combination. I can't tell if I'm about to pass out b/c I'm sick, or my body is just out of whack.

      Thanks guys.
Re: A would-be simple substitution...
by Aristotle (Chancellor) on Mar 02, 2004 at 10:24 UTC
    Semantically you are composing a new value for the variable; why not write the code that way as well?
    $time = "$1:$2:$3.$4" if $time =~ /^(\d{2})(\d{2})(\d{2})\.(\d{2})/;
    This also makes it easier to yell if the data didn't conform to expectations:
    if($time =~ /^(\d{2})(\d{2})(\d{2})\.(\d{2})/) { $time = "$1:$2:$3.$4"; } else { die "Malformed time: $time\n"; }

    Makeshifts last the longest.

Re: A would-be simple substitution...
by gmpassos (Priest) on Mar 02, 2004 at 20:28 UTC
    Remember that ".+?" is not doing what you think!

    If you want to indicate 0 or more matches, the regexp operator is "*".

    The combination of +? and *? tells that it will match until find the next occurrence. Soo, we use this combination for things like that:

    ## to look until find > /<.*?>/ ## if we use just .*, the next occurrence will never be ## found, since .* already get everything. ## So +? is just the same thing of .*, but is for 1 or ## more occurrences.
    Cheers.

    Graciliano M. P.
    "Creativity is the expression of the liberty".

Re: A would-be simple substitution...
by Anonymous Monk on Mar 03, 2004 at 08:28 UTC
    This works
    #!/usr/bin/perl # # use strict; use warnings; my $time = "123456.745768"; my $time2 = "123456.745768"; $time =~ s/^(\d{2})(\d{2})(\d{2})\.(\d{2})\d{4}/$1:$2:$3.$4/; $time2 =~ s/^(\d{2})(\d{2})(\d{2})\.(\d{2})\d*$/$1:$2:$3.$4/; print "$time\n"; print "$time2\n";