use strict; use warnings; # From http://prometheus.frii.com/%7Egnat/yapc/2000-stages/slide31.htm +l # Fixed a typo in the regex (Nathan forgot to escape the forwardslash. +) while (<DATA>) { chomp; my $celsius = my $fahrenheit = $_; #was $fahrenheit =~ s|(\d+)C|($1*9/5)+32 . "F"|ge; $fahrenheit =~ s|(\d+\.\d+)C|($1*9/5)+32 . "F"|ge; print "$celsius is $fahrenheit\n"; } #Outputs: #12C is 12C #16.5C is 61.7F #-40C is -40C __DATA__ 12C 16.5C -40C
UPDATE: Fixed regex to find decimals, after JDPorter pointed out the problem below. (And before Tanktalus beat me to it ;) )

Replies are listed 'Best First'.
Celsius to Fahrenheit using Regexp::Common
by tphyahoo (Vicar) on Feb 09, 2005 at 11:02 UTC
    Thanks to everyone for their wisdom. I agree that s/// isn't in principle the best way to do this, I just was playing with the eval functionality in RHS (right hand side). Hey, if it's good enough for Nathan Torkington (see url at top of comments), it should be good enough for me, right?

    But I kept getting comments that there was something wrong with the regex. First, it didn't work with negatives. Then, it didn't work with decimals. Then, it worked *only* with decimals.

    Well, I got tired of this back and forth, so here's the same code using Damian Conway's Regexp::Common::Number in the LHS (left hand side). If there's still some issue here, submit a bug report to CPAN. ;)

    use strict; use warnings; use Regexp::Common; # From http://prometheus.frii.com/%7Egnat/yapc/2000-stages/slide31.htm +l # Fixed a typo in the regex (Nathan forgot to escape the forwardslash. +) while (<DATA>) { chomp; my $celsius = my $fahrenheit = $_; #was $fahrenheit =~ s|(\d+)C|($1*9/5)+32 . "F"|ge; # But that didn't work with decimals #was $fahrenheit =~ s|(\d+\.\d+)C|($1*9/5)+32 . "F"|ge; #but that required decimals #This is getting ridiculous, so let's just use Damian Conway's Regex +p::Common $fahrenheit =~ s|($RE{num}{real})C|($1*9/5)+32 . "F"|ge; print "$celsius is $fahrenheit\n"; } #Outputs: #-2C is 28.4F #-1.5C is 29.3F #-1C is 30.2F #-1.0C is 30.2F #0C is 32F #0.0C is 32F #.1C is 32.18F #0.1C is 32.18F #1C is 33.8F #+1C is 33.8F #1.5C is 34.7F #+1.5C is 34.7F #2C is 35.6F __DATA__ -2C -1.5C -1C -1.0C 0C 0.0C .1C 0.1C 1C +1C 1.5C +1.5C 2C
Re: Celsius to Fahrenheit using s///
by jdporter (Paladin) on Feb 08, 2005 at 15:11 UTC
    I suppose the point of that little exercise is to show how /e works.
    But for practical purposes, it's pretty useless:
    16.5C is 16.41F -40C is -104F

      Almost as easy to fix it as to find the problem ;->

      use strict; use warnings; # From http://prometheus.frii.com/%7Egnat/yapc/2000-stages/slide31.htm +l # Fixed a typo in the regex (Nathan forgot to escape the forwardslash. +) # Fixed number problems - allow +/-, and decimals. Exponentials still + not allowed. while (<DATA>) { chomp; my $celsius = my $fahrenheit = $_; $fahrenheit =~ s|([+-]?(?:\d*\.)?\d+)C|($1*9/5)+32 . "F"|ge; print "$celsius is $fahrenheit\n"; } #Outputs: #12C is 53.6F #13C is 55.4F #14C is 57.2F #15C is 59F #-40C is -40F #+32C is 89.6F #.5C is 32.9F #15.8C is 60.44F __DATA__ 12C 13C 14C 15C -40C +32C .5C 15.8C

        Using the /e modifier of a regex for such uses is just plain wrong. It looks more like you are obfuscating code than writing it. Much better written in a form such as the following (mine will also do reverse conversions -- F to C):

        #!/usr/bin/perl -w use strict; while (<DATA>) { chomp; next unless (m!\A([+-]?(?:\d*\.)?\d+)([CF])\z!); print "$_ is ", ( $2 eq 'C' ? $1 * 9 / 5 + 32 . 'F' : ($1 - 32) * 5 / 9 . 'C' ), $/; } __END__ 12C 13C 14C 15C -40C +32C .5C 15.8C 60.44F 55.4F -.7F