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

Hello,
Between pattern1 and pattern2, I'd like to do a substitution. I got it to work so that it prints to change to stdout, but it won't do the in-place edit of the file.
Here is my script so far:

#!/usr/bin/perl #print "ARGV:", $#ARGV; if ($#ARGV == 2 ) { my $host = $ARGV[0]; my $fn = $ARGV[1]; my $value = $ARGV[2]; #print "INPUTS: host:$host, fn:$fn, value:$value\n\n"; $systemsconfig = '/usr/local/etc/system.ini'; system("cp $systemsconfig /tmp/reconfig"); open CONFIG, "+< $systemsconfig" or die "Couldn't open $systemsconfi +g"; $^I = ".bak"; while (<CONFIG>) { if ( $_ =~ m/^\[$host\]/ .. m/#END/ ) { $_ =~ s/$fn=(.*)/$fn=$value/; print; # i thought print CONFIG here??? } } close CONFIG; }

Here is an example of the file that needs to be edited:

[bdstest] MainFunction= SystemType=U5 Env= Location= Serial=FW0094810719 Hostid=80c0dc14 OS=Solaris Version=8 Disk=1x8 Memory=128 CPU=1x360 qfe= SCSI= GraphACC= SupportContract= #END [custard] MainFunction= SystemType=U5 Env= Location= Serial=FW00250126 Hostid=80c0aee2 OS=Solaris Version=8 Disk=1x8 Memory=256 CPU=1x360 qfe= SCSI= GraphACC= SupportContract= #END

EXAMPLE: I'd like to edit the MainFuntion= line between bdstest and #END

So I call the script like this:

/usr/local/etc/test.pl bdstest MainFunction oracle

The system.ini file is in that format because this function will become part of a perl mod I'm slowly building to use it to integrate with some bash scripts to allow people to check out configuration information (I use Config::IniFiles)

Thanks for any help!
Rob

20031126 Edit by Corion: Added formatting

Replies are listed 'Best First'.
Re: In-place editing in a script
by eric256 (Parson) on Nov 26, 2003 at 20:09 UTC

    Is there any reason not to just use Config::IniFiles to do the editing as well as reading? From the docs it look like you want...

    $cfg->setval ($host,$fn, $value);

    Of course you need to handle loading and saving the file agian as well. As for why your code doesn't work, it looks like you open a single file and read from it. Try opening the file to read from, and the temp file to write to. Then copying the temp file over the old file after closeing them both.


    ___________
    Eric Hodges
      That's a great idea! I just started using Config::IniFiles and haven't thought of using the setval fn. I'm working that now. It would still be cool to know how to do a substition within a range. It's great to $_ =~ s/$pattern1/$pattern2/ but to do something like $_ =~ m/BEGIN/ .. m/END/s$pattern1/$pattern2... Anyway, thanks for your help! Perl is getting more and more and more and more cool /Rob
        It's very simple to do search and replace with s/// on simple config files, without using any modules. And you don't need a temporary file either, just load the entire config file into memory, search and replace keys, and write it back to the config file. Perl is great at doing this kind of stuff.

        use strict; use Data::Dumper; my @config; { local $/ = '['; @config = <DATA>; } SetConfigKey(\@config, 'bdstest', 'Location', 'Somewhere'); SetConfigKey(\@config, 'bdstest', 'OS', 'WindowsXP'); SetConfigKey(\@config, 'custard', 'MainFunction', 'Perl Perl Perl'); SetConfigKey(\@config, 'custard', 'SCSI', 'YES'); print @config; sub SetConfigKey { my ($config, $section, $key, $value) = @_; foreach (@{$config}) { # loop through config sections next if ! /^$section\]/; # skip if unwanted s/\Q$key\E\s*=.*/$key=$value/; # replace the value } } __DATA__ [bdstest] MainFunction= SystemType=U5 Env= Location= Serial=FW0094810719 Hostid=80c0dc14 OS=Solaris Version=8 Disk=1x8 Memory=128 CPU=1x360 qfe= SCSI= GraphACC= SupportContract= #END [custard] MainFunction= SystemType=U5 Env= Location= Serial=FW00250126 Hostid=80c0aee2 OS=Solaris Version=8 Disk=1x8 Memory=256 CPU=1x360 qfe= SCSI= GraphACC= SupportContract= #END
        And the output is -
        [bdstest] MainFunction= SystemType=U5 Env= Location=Somewhere Serial=FW0094810719 Hostid=80c0dc14 OS=WindowsXP Version=8 Disk=1x8 Memory=128 CPU=1x360 qfe= SCSI= GraphACC= SupportContract= #END [custard] MainFunction=Perl Perl Perl SystemType=U5 Env= Location= Serial=FW00250126 Hostid=80c0aee2 OS=Solaris Version=8 Disk=1x8 Memory=256 CPU=1x360 qfe= SCSI=YES GraphACC= SupportContract= #END