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

Your holinesses. I have a system file with a case statement like this. I need to check and see if the entry 'bgs' is correct? This one is no +t. Most of them are not. I have several hundred files I need to change. Many don't have it. So, for this file I need to change: /sbin/sh /usr/adm/best1_default/bgs/scripts/best1agent_start>>$LOG 2>> +$LOG to: '/usr/bin/su - patrol /usr/adm/best1_default/bgs/scripts/best1agent -q +' Which is strait forward. I leave the ones that are ok alone. Change the ones that are wrong. Add the 3 lines if they are not there after a trigger of something lik +e 'cron'. 'bgs') '/usr/bin/su - patrol /usr/adm/best1_default/bgs/scripts/best1agent + -q' ;; I thought it would be easy. But, I'm having a hell of a time with it. + I've tryed several diferent ways. Logic: I'm not sure about? foreach through the files. open() and while() through each file. check for $line to see if it needs to be changed. If it does, Change it. If not leave it alone. BUT, what if it doesn't have the $line at all? I was thinking early on + in the script to use grep. But, I can't get that to work. Any suggestions would be much appreciated. FILE TO CHANGE: case "$process" in 'cron') /sbin/sh /etc/rc2.d/S75cron start >>$LOG 2>>$LOG ;; 'secmgrd') echo "Starting SECMGRD" >>$LOG /sbin/sh /etc/init.d/iv stop >>$LOG 2>>$LOG /sbin/sh /etc/init.d/iv start >>$LOG 2>>$LOG return ;; 'bgs') /sbin/sh /usr/adm/best1_default/bgs/scripts/best1agent_start>>$LOG +2>>$LOG ;; 'twagent') /sbin/sh /etc/rc2.d/S95twagent start>>$LOG 2>>$LOG ;; 'bvcontrold') /sbin/sh /etc/init.d/bvunix start>>$LOG 2>>$LOG ;; 'dsmcad') /sbin/sh /etc/init.d/adsm_sched>>$LOG 2>>$LOG ;; *) return ;; esac
Thank You

Replies are listed 'Best First'.
Re: I need some pearls of wisdom
by hipowls (Curate) on Feb 23, 2008 at 00:39 UTC

    This is easier from the command line

    perl -i.bak -pe's{/sbin/sh\s+/usr/adm/best1_default/bgs/scripts/best1a +gent_start\s*>>\s*\$LOG\s+2>>\s*\$LOG\s*$} {/usr/bin/su - patrol /usr +/adm/best1_default/bgs/scripts/best1agent -q}'
    you can use find to find the files that you want to change.
    find <directory list> <predicates> -exec perl -i.bak -pe'...' {} \;
    If you are feeling very brave you can drop the .bak from the command line but it is safer to remove the backups after you have checked the result.
    find <directory list> -name '*.bak' | xargs rm

    Disclaimer: I haven't run this command line on any of my files. I suggest you test it on a copy of a known bad file first.

Re: I need some pearls of wisdom
by pc88mxer (Vicar) on Feb 23, 2008 at 17:06 UTC
    Just a couple of comments...

    The above suggestion is good advice, but I never liked the way that perl's -i option worked. One problem is that if you accidentally run your script twice you've just blown away your originals. Also, it's not 'transactional'. For some edits I want to be able to die and not have the original file change. For quick-and-dirty operations it can work well, but I wouldn't recommend using it for a massive editing process like you're describing. Rather, I would recommend that you:

    • First make a backup of all the scripts you want to edit.
    • Edit the (backup copy of the) files.
    • Verify the changes are what you want.
    • Install the new versions of the files into their original locations.

    Making the back-up copies can be done easily using the --parents switch to cp, i.e.:

    mkdir backups find ... -exec cp --parents '{}' backups ';'

    and this will preserve the parent path of the found files.

    The other comment I have is that if you have several hundred files to edit, it might be helpful to reconsider how they are organized. It seems that your scripts are organized by <verb> <noun>, i.e. the script is the verb and the thing to act on is passed as an argument. You might look into changing this around so that the noun selects the script and the action is supplied as an argument. So instead of running:

    $ start bgs

    you would start up the bgs daemon by running:

    $ bgs start

    This will make your scripts more 'object oriented' and place similar concerns in the same script. Also, when you deploy a new version of the bgs daemon, you wouldn't have to edit all the 'start' scripts to include the new bgs code, you would just be replacing one bgs control script. Anyway, it's something to consider to see if it's applicable to your situation.

      It is not an option to how I start it up. Each one of these files gets rsync'd to a server. This isn't even the confusing part. I also have to modify an sh script that sends a trap to Openview. But, I am not going to add that into the mix. till I figure the first part out. But, If I can figure this out. That will be easy. You are just changing one line with the code above. I need to either change the line, leave it alone. Or add a whole new line to it. I need to get motivated and start playing with it some more.