Confused Newbie question: Decimal to IP

Discussion in 'Perl Misc' started by Monica Roman, May 10, 2004.

  1. Monica Roman

    Monica Roman Guest

    I've read a lot of the threads on this conversion but could not figure
    out which one is the correct function.

    I have never written PERL before, but I want to give it a try and be
    able to convert decimal numbers into IP addresses in the PERL script
    used to load the IPs plus other data into an Oracle database. Right
    now I use a SQL function within Oracle, but it slows down everything!

    Can someone help the translate into PERL the following SQL function?

    create or replace function int2ip(ip int)
    return varchar2
    is
    ip_address varchar2(15);
    t number;
    w int(3);
    x int(3);
    y int(3);
    z int(3);

    begin

    t:= ip / 256;
    w:= 256 * (t - FLOOR(t));
    t:= (FLOOR (t))/ 256;
    x:= 256 * (t - FLOOR(t));
    t:= (FLOOR (t)) / 256;
    y:= 256 * (t - FLOOR(t));
    z:= FLOOR (t);

    ip_address := z||'.'||y||'.'||x||'.'||w;

    return ip_address;
    end int2ip;


    Thank you very much,


    Monica Roman
    Monica Roman, May 10, 2004
    #1
    1. Advertising

  2. Monica Roman wrote:
    > I've read a lot of the threads on this conversion but could not figure
    > out which one is the correct function.
    >
    > I have never written PERL before, but I want to give it a try and be
    > able to convert decimal numbers into IP addresses in the PERL script
    > used to load the IPs plus other data into an Oracle database. Right
    > now I use a SQL function within Oracle, but it slows down everything!

    <snip horrific pl/sql> (yes, I know that that is its nature)

    look at inet_ntoa in the Socket module for starters.

    perldoc Socket

    btw: it's written "Perl" or "perl".

    regards,

    Mark
    Mark Clements, May 10, 2004
    #2
    1. Advertising

  3. Monica Roman <> wrote:

    > I've read a lot of the threads on this conversion but could not figure
    > out which one is the correct function.



    Have you tried the Perl FAQ?


    > I have never written PERL before,



    There is no PERL, there is only Perl and perl.


    > Can someone help the translate into PERL the following SQL function?



    Yes. _You_ can.

    If you run into trouble post what you have so far and we will
    help you fix it.


    > t:= ip / 256;
    > w:= 256 * (t - FLOOR(t));



    The assignment, division, multiplication and subtraction operators are
    documented in:

    perldoc perlop


    The floor() function is a Question that is Asked Frequently:

    perldoc -q floor

    Does Perl have a round() function? What about ceil() and floor()?
    Trig functions?


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
    Tad McClellan, May 10, 2004
    #3
  4. Monica Roman wrote:
    >
    > I've read a lot of the threads on this conversion but could not figure
    > out which one is the correct function.
    >
    > I have never written PERL before, but I want to give it a try and be
    > able to convert decimal numbers into IP addresses in the PERL script
    > used to load the IPs plus other data into an Oracle database. Right
    > now I use a SQL function within Oracle, but it slows down everything!
    >
    > Can someone help the translate into PERL the following SQL function?
    >
    > create or replace function int2ip(ip int)
    > return varchar2
    > is
    > ip_address varchar2(15);
    > t number;
    > w int(3);
    > x int(3);
    > y int(3);
    > z int(3);
    >
    > begin
    >
    > t:= ip / 256;
    > w:= 256 * (t - FLOOR(t));
    > t:= (FLOOR (t))/ 256;
    > x:= 256 * (t - FLOOR(t));
    > t:= (FLOOR (t)) / 256;
    > y:= 256 * (t - FLOOR(t));
    > z:= FLOOR (t);
    >
    > ip_address := z||'.'||y||'.'||x||'.'||w;
    >
    > return ip_address;
    > end int2ip;


    A direct Perl translation would be something like:

    use POSIX qw( floor );

    sub int2ip {
    my $ip = shift;

    my $t = $ip / 256;
    my $w = 256 * ( $t - floor $t );
    $t = floor( $t ) / 256;
    my $x = 256 * ( $t - floor $t );
    $t = floor( $t ) / 256;
    my $y = 256 * ( $t - floor $t );
    my $z = floor $t;

    return "$z.$y.$x.$w";
    }


    However that is still relatively slow. A more Perlish solution would
    be:

    sub int2ip { join '.', unpack 'CCCC', pack 'N', $_[ 0 ] }


    Which is a lot faster. But an even faster solution would be:

    use Socket;

    sub int2ip { inet_ntoa inet_aton $_[ 0 ] }



    John
    --
    use Perl;
    program
    fulfillment
    John W. Krahn, May 11, 2004
    #4
  5. Monica Roman

    Anno Siegel Guest

    John W. Krahn <> wrote in comp.lang.perl.misc:
    > Monica Roman wrote:


    [...]

    > > Can someone help the translate into PERL the following SQL function?
    > >
    > > create or replace function int2ip(ip int)
    > > return varchar2
    > > is
    > > ip_address varchar2(15);
    > > t number;
    > > w int(3);
    > > x int(3);
    > > y int(3);
    > > z int(3);
    > >
    > > begin
    > >
    > > t:= ip / 256;
    > > w:= 256 * (t - FLOOR(t));
    > > t:= (FLOOR (t))/ 256;
    > > x:= 256 * (t - FLOOR(t));
    > > t:= (FLOOR (t)) / 256;
    > > y:= 256 * (t - FLOOR(t));
    > > z:= FLOOR (t);
    > >
    > > ip_address := z||'.'||y||'.'||x||'.'||w;
    > >
    > > return ip_address;
    > > end int2ip;

    >
    > A direct Perl translation would be something like:
    >
    > use POSIX qw( floor );
    >
    > sub int2ip {
    > my $ip = shift;
    >
    > my $t = $ip / 256;
    > my $w = 256 * ( $t - floor $t );
    > $t = floor( $t ) / 256;
    > my $x = 256 * ( $t - floor $t );
    > $t = floor( $t ) / 256;
    > my $y = 256 * ( $t - floor $t );
    > my $z = floor $t;
    >
    > return "$z.$y.$x.$w";
    > }


    [snip other solutions]

    That can be Perlified a bit (no critique, the OP asked for a direct
    translation):

    sub int2ip {
    my $ip = shift;
    $ip *= 256;
    join '.', reverse map $_ % 256, map $ip = floor( $ip/256), 1 .. 4;
    }

    I mention this because it shows a particular difficulty. The step

    "map $ip = floor( $ip/256), 1 .. 4"

    is meant to produce a list of iterative applications of "floor( $ip/26)"
    to $ip. So it does, but the list starts with the operation applied
    once to $ip while we want the list to start with the original value of
    $ip (the operation applied zero times).

    In the given case that could be corrected by multiplying $ip with 256
    first, but that's not always applicable, ugly and fragile.

    Other possibilities are

    map { my $sav = $ip; $ip = floor( $ip/256); $sav} 1 .. 4;
    or
    map ( "$ip", $ip = floor( $ip/256))[ 0], 1 .. 4;
    or
    ( "$ip", map $ip = floor( $ip/256), 2 .. 4);

    but I can't say I like either very much. So currently I'd probably
    write this

    my @coll;
    for ( 1 .. 4 ) {
    push @coll, $ip;
    $ip = floor( $ip/256);
    }

    but I can't help thinking there must be a nice map solution.

    Is there?

    Anno
    Anno Siegel, May 11, 2004
    #5
  6. Monica Roman

    Monica Roman Guest

    Thank you Mark, John, Tad, for all your answers. John, I'll try all
    the options you gave me...nothing better than something tangible to
    start learning Perl, a question with the answer, perfect. I have two
    Perl books on my desk right now and I'm excited about learning it.

    Thanks again,

    Monica
    Monica Roman, May 11, 2004
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ven
    Replies:
    3
    Views:
    1,318
  2. Gilbert Fine
    Replies:
    8
    Views:
    897
    Zentrader
    Aug 1, 2007
  3. Vitaliy
    Replies:
    1
    Views:
    471
    Peter Otten
    May 29, 2008
  4. valpa
    Replies:
    11
    Views:
    1,505
    Steven D'Aprano
    Mar 24, 2009
  5. Replies:
    0
    Views:
    285
Loading...

Share This Page