use strict; use warnings; # Update $fname re-runnably. # $fcontents is either a string or a reference to an array of lines. sub atomic_update { my ( $fname, $fcontents ) = @_; print "updating '$fname'..."; my $bak = $fname . $$ . '.tmp'; -e $bak and ( unlink($bak) or die "error: unlink '$bak': $!" ); open( my $fh, '>', $bak ) or die "error: open '$bak': $!"; print {$fh} ref($fcontents) ? @{$fcontents} : $fcontents or die "error: print '$bak': $!"; close($fh) or die "error: close '$bak': $!"; rename( $bak, $fname ) or die "error: rename '$bak' '$fname': $!"; print "done.\n"; } my $hostfile = shift || "C:/Windows/System32/drivers/etc/hosts"; print "hostfile : $hostfile\n"; open(my $In, '<', $hostfile) or die "error: open '$hostfile': $!"; my @Output = <$In>; close $In; # If 10.10.1.2 is commented out, uncomment it. # If it is not commented out, comment it out. my $nchanges = 0; for (@Output) { if ( s/^#(?=10\.10\.1\.2\b)// ) { ++$nchanges; next; } if ( s/^(?=10\.10\.1\.2\b)/#/ ) { ++$nchanges; next; } } if ($nchanges > 0) { atomic_update( $hostfile, \@Output ); } print "There were $nchanges changes made to file '$hostfile'\n";