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

Hello all you Monks!

I am opening a file and want to check for a line and make a substitution or if the line does not exist write a new line. The straight substitution work well. The one to write the IP is the problem.

What is happening is that the new line is getting written after each existing line instead of getting written once.

Here is my code:

print "Please enter the ip address for this machine. This will be eth +0:\n"; my $ip = <>; chomp $ip; my $if0 = "ifcfg-eth0"; my $if1 = "ifcfg-eth1"; my $ifdir = 'network-scripts'; my $ifsub1 = "IPADDR="; my $ifsub2 = "BOOTPROTO="; my $ifsub3 = "none"; open (IP, "<", "$dir/$sys/$ifdir/$if0"); open (NEW, ">", "$dir/$sys/$ifdir/$if0.new"); while (<IP>){ s/^$ifsub2.*/$ifsub2$ifsub3/; s/^$ifsub1.*/$ifsub1$ip/ || print "$ifsub1$ip\n"; print $_; #print "$ifsub1$ip\n"; <==I tried it here too } close IP; close NEW;

Here is the output:

IPADDR=1.1.1.1 # Advanced Micro Devices [AMD] 79c970 [PCnet32 LANCE] IPADDR=1.1.1.1 DEVICE=eth0 IPADDR=1.1.1.1 BOOTPROTO=none IPADDR=1.1.1.1 DHCPCLASS= IPADDR=1.1.1.1 HWADDR=00:0C:29:97:01:F3 IPADDR=1.1.1.1 ONBOOT=yes

The original file looks like this:

# Advanced Micro Devices [AMD] 79c970 [PCnet32 LANCE] DEVICE=eth0 BOOTPROTO=dhcp DHCPCLASS= HWADDR=00:0C:29:97:01:F3 ONBOOT=yes

Thanks for your help!

John

Replies are listed 'Best First'.
Re: How to write a new line in a while loop?
by ikegami (Patriarch) on Oct 06, 2009 at 22:23 UTC

    You're doing a substitution at every line.

    A "one-liner" solution:

    perl -i.bak -nle' BEGIN { print("IPADDR=", shift(@ARGV)) } print if !/^IPADDR=/; ' 1.1.1.1 dir/sys/network-scripts/ifcfg-eth0

    A script solution:

    print("IPADDR=$ip\n"); while (<$fh_in>) { print $fh_out $_ if !/^IPADDR=/; }

    If you wanted to use substitution (to maintain order), it would look like

    my $found = 0; while (<$fh_in>) { ++$found if s/^IPADDR=.*/IPADDR=$ip/; print $fh_out $_; } print("IPADDR=$ip\n") if !$found;

      Perfect! Solution 3 is exactly what I needed. Thank you!

Re: How to write a new line in a while loop?
by gsiems (Deacon) on Oct 06, 2009 at 22:16 UTC

    If I understand you correctly, you are wanting to do the equivalent of:

    grep -v IPADDR "$dir/$sys/$ifdir/$if0" > "$dir/$sys/$ifdir/${if0}.new" echo "IPADDR=1.1.1.1" >> "$dir/$sys/$ifdir/${if0}.new"

    at the command line. If this is the case, do you really need perl for this or is this part of a larger script/problem?

    --gsiems

    Update: Looking closer, I see that I missed the BOOTPROTO line. Is this closer to what you are looking for (not tested):

    print "Please enter the ip address for this machine. This will be eth +0:\n"; my $ip = <>; chomp $ip; my $if0 = "ifcfg-eth0"; my $if1 = "ifcfg-eth1"; my $ifdir = 'network-scripts'; my $ifsub1 = "IPADDR="; my $ifsub2 = "BOOTPROTO="; my $ifsub3 = "none"; my $IP; my $NEW; open ($IP, "<", "$dir/$sys/$ifdir/$if0"); open ($NEW, ">", "$dir/$sys/$ifdir/$if0.new"); my @ary = ( grep { $_ !~ m/IPADDR/ } (<$IP>)); s/($ifsub2).+$/$1$ifsub3/ for @ary; print $NEW @ary; print $NEW "IPADDR=$ip\n"; close $IP; close $NEW;