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

I think I'm just down to the regular expression I need to find the line in the hosts file. I am bound by the modules already implemented within the Perl build on the laptops which does not include Regex so I can't use $RE{net}{IPv4}. In the following segment of the script I have the expression to verify that there are four :

if( $vmServerIP =~ m/^(\d\d?\d?)\.(\d\d?\d?)\.(\d\d?\d?)\.(\d\d?\d?)/ +){ if($1 <= 255 && $2 <= 255 && $3 <= 255 && $4 <= 255){ open (my $oldhfile, ,'<', $hfilepath) or die "Could not open $hf +ilepath for reading."; my @hfile = <$oldhfile>; # # read each line to find the lines that lead with an IP address # and then find the line with HOSTNAME in it and replace that IP # address with the provided one # foreach $hfileline (@hfile) { next unless $hfileline =~/^\s*\s+$hNames/; $hfileline = "$vmServerIP $hNames\n"; }

I'm pretty sure that the validation of the format of the octets is working correctly. However, I'm having issues with formulating the regular expression in the foreach loop if anyone could provide me with some guidance.

-nas

Replies are listed 'Best First'.
Re: update winxp hosts file with new IP address
by tachyon-II (Chaplain) on May 08, 2008 at 04:58 UTC

    You need to define what you mean by your default IP address. Essentially the hosts file on Win32 typically contains just an entry for localhost. If this is all you have, plus another IP then all you need to do is overwrite the old hosts file with new data, rather than mess around with finding one IP and replacing it.

    my $hosts = "C:/windows/system32/drivers/etc/hosts"; print "Line to add to hosts (x.x.x.x domain.com): "; my $line = <STDIN>; rename( $hosts, "$hosts.old" ); # effectively make backup open FILE, ">$hosts" or die "Can't write $hosts $!\n"; print FILE "127.0.0.1 localhost\n$line"; close FILE;

    If you actually want to find a line and replace it the approach is a little different.

    my $hosts = "C:/windows/system32/drivers/etc/hosts"; print "Line to add to hosts (x.x.x.x domain.com): "; my $line = <STDIN>; print "IP to replace: "; chomp( my $ip = <STDIN> ); rename( $hosts, "$hosts.old" ); open IN, "$hosts.old" or die "Can't read $hosts.old $!\n"; open OUT, ">$hosts" or die "Can't write $hosts $!\n"; while (my $old = <IN>) { print OUT $old unless $old =~ m/\Q$ip/; } print OUT $line; # add the new record close IN; close OUT;

    If you just want to change the IP then you need to get the old ip and new ip in like at the start (remember to chomp input to remove newline). Within the loop you would just do:

    $old =~ s/\Q$old_ip\s+/$new_ip /; print OUT $old;

    and drop the print after the loop.

    You can do it in a one liner. This particular syntax can come in very handy:

    C:\>perl -pi.bak -e "s/this/that/g" <file>

    This makes a backup called file.bak and replaces all instances of this with that in the original

Re: update winxp hosts file with new IP address
by pc88mxer (Vicar) on May 08, 2008 at 04:16 UTC
    ...and finding the default IP address and replacing it with the new value.
    What do you mean by 'default IP address'? What hostname is it associated with?

    Since the hosts file shouldn't change that much, here's a simple approach that might work for you:

    1. Create a copy of the hosts file without the default ip address entry. Call this file hosts-base
    2. When the default IP address needs to changed, copy hosts-base to hosts and append the new default address entry.
    The script to perform step 2 can even be a .bat file, but here's a perl script:
    open(B, "<c:/path/to/hosts-base"); open(N, ">c:/path/to/hosts"); while (<B>) { print N; } print N "default $ARGV[0]\n"; # add the 'default' entry
    If the default IP address is limited to a couple of different choices, then you can just prepare one host file for each possible value for the default IP address, and copy the desired file to the real hosts file as required.
Re: update winxp hosts file with new IP address
by CountZero (Bishop) on May 08, 2008 at 05:49 UTC
    My hosts file looks like this:
    # Copyright (c) 1993-1999 Microsoft Corp. # # This is a sample HOSTS file used by Microsoft TCP/IP for Windows. # # This file contains the mappings of IP addresses to host names. Each # entry should be kept on an individual line. The IP address should # be placed in the first column followed by the corresponding host nam +e. # The IP address and the host name should be separated by at least one # space. # # Additionally, comments (such as these) may be inserted on individual # lines or following the machine name denoted by a '#' symbol. # # For example: # # 102.54.94.97 rhino.acme.com # source server # 38.25.63.10 x.acme.com # x client host 127.0.0.1 localhost 192.168.1.108 chrome 192.168.1.105 legba

    Suppose the aptly named legba machine is the default and you need to change its IP address.

    # set_default_host.pl use strict; use Regexp::Common qw /net/; if (scalar @ARGV == 1 and $ARGV[0]=~/^$RE{net}{IPv4}$/) { my $path2hostsfile = 'C:/Windows/System32/drivers/etc/hosts'; my @hostsfile; { open(my $from_hostsfile, '<', $path2hostsfile) or die "Could n +ot open $path2hostsfile for reading"; @hostsfile = <$from_hostsfile>; } foreach my $line (@hostsfile) { next unless $line =~/^\s*$RE{net}{IPv4}\s+legba/; # skip unles +s it is the default entry $line = "$ARGV[0] legba\n"; # change the default host. $li +ne is an alias for the corresponding element of @hostsfile! } { open(my $to_hostsfile, '>', $path2hostsfile) or die "Could n +ot open $path2hostsfile for writing"; print $to_hostsfile @hostsfile; } } else { print "Missing or wrong argument!\nusage: set_default_host.pl defa +ult_IP\n"; }
    Save this program as set_default_host.pl and run it in a "dos box" (command line). It takes one argument: the new default IP.

    The program checks if this argument is present and is indeed an IP.

    You will have to adapt the program slightly so the regex matches your default host. It is unlikely your default host will be called 'legba' although obviously that is highly recommended!

    Update: added "or die ..." to open

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      Thank you all for your responses. You are correct in that I should have provided more detail. Normally I would have. I will blame the late hour of the posting and my failed attempts to get anything working on my own.

      CountZero, you hit the situation precisely on the head. Thank you very much for the detailed example! The regular expressions search for the correct line to replace the IP address on is the main part I was having issues with.

      -nas

        This is what I came up with based on the information provided and the desire to have the user prompted for the updated IP address.

        Please let me know if I'm making some serious Perl mistakes or if this looks good. Hints about better coding are always appreciated.

        Update: Removed the code here. I hadn't tested it on the intended workstation before posting it and it turned out that it didn't work properly because the laptop image didn't include the Regex module.

        Thanks once again for the guidance!

Re: update winxp hosts file with new IP address
by Anonymous Monk on May 08, 2008 at 04:11 UTC