Icon The Kermit Project   |   Now hosted by Panix.com
New York City USA   •   kermit@kermitproject.org
…since 1981

Replacetextblock

[download

    A Kermit script to replace blocks of text within files

Author:  Frank da Cruz
Script version: 1.01
Dated: 2014/02/28
      Platform:  Any version of Unix where C-Kermit is available.
Requires:  C-Kermit 9.0 or later
This page last updated: Fri Feb 28 11:46:39 2014

Replacetextblock is a program written in the Kermit script language that answers the frequently asked question, “How do I replace a block of text in a group of files with a different block of text without having to manually edit each file?”. A Google search doesn't turn up any good answers, so here is a Kermit script that probably does just want you want.

Installation

If you have already downloaded and installed getkermitscript, use it to install Replacetextblock:
cd (to desired directory that is in your PATH)
getkermitscript replacetextblock
If not, visit the getkermitscript page to download and install it, or at least to read how to download and install scripts the traditional tedious way (save, chmod, edit...). If you just want to look at the source code (and maybe save it), CLICK HERE.

Using Replacetextblock

The script is called Replacetextblock because it replaces a block of text, not just one line. A text block is defined as a contiguous series of zero or more complete lines (not pieces of lines).

C-Kermit 9.0.304 already has a CHANGE command that can be used to replace text within a line or whole text lines in a group of files, but the CHANGE command does not operate on a blocks of text, such as:

When you have large numbers of files that contain identical blocks of text like this, and then you need to change them for some reason, you have the perfect application for Replacetextblock.

In fact, Replacetextblock is even a bit more flexible that that. Suppose, for example, you have software source code broken up into 200 modules. Each module contains a copyright notice, but the year might different:

/*
 * Copyright (c) 1986, 1990, XYZ Corporation. All rights reserved.
 * See the COPYING file for copyright and license information.
 */
Other source files might say "Copyright (c) 1986, 2007", or other years. Suppose that for some reason (for example, the copyright was sold to another company) you want to change the text of all these notices, and also to update the copyright year. You can create an "oldtext" file containing a lines that contain patterns that match these notices:
 \* Copyright (c) 1986, {19,20}[0-9][0-9], XYZ Corporation. All rights reserved.
 \* See the COPYING file for copyright and license information.

{19,20}[0-9][0-9]” is a pattern that matches all four-digit numbers starting with 19 or 20, i.e. all years in the 20th and 21st Centuries. Backslash (\) has been placed in front of the asterisks because '*' is a pattern-matching character but in this case we want to take it literally. You can read about Kermit's pattern matching HERE.

Replacetextblock uses the oldtext file to search through the files you've specified. Then a second file, the newtext file, which contains the new replacement text is substituted into each file in place of the lines that match the first file. The newtext file might look like this:

 * Copyright (c) 1986, 2014, ABC Corporation. All rights reserved.
 * This package has new licensing terms.
 * See the LICENSE file for copyright and license information.
Then to update all the files (let's suppose they are C-language source files), you would do something like this:
replacetextblock oldtext newtext *.[ch] makefile

If you want to remove the oldtext without replacing it with anything, you can give the name of an empty file or simply use Unix's built-in empty file, /dev/null for newtext:

replacetextblock oldtext /dev/null *.html
Normally, as the script runs, it prints the name of each file it is processing, and whether it it found and replaced the desired text:
[~/mm] replacetextblock oldtext newtext [ab]*.[ch]
action.c...OK (text was replaced)
alias.c...OK (text was replaced)
args.h...(replacement text not found - no change was made)
argsort.c...OK (text was replaced)
babyl.h...OK (text was replaced)
If the text was not found in a particular file, that file is not touched. If a file was changed, the script makes a backup of the original file having the same name but with .backup appended to it (you can defeat this behavior with a command-line option, next section). The updated file has the same permissions as the original, but its modification time is updated.

The size and number of the lines in the oldtext and newtext files don't have to be the same; you can (for example) replace a short text with a long one or vice versa.

The Replacetextblock command line

Replacetextblock is controlled by its command-line arguments. The format is:
replacetextblock [ option [ option [ ... ] ] ] oldtext newtext file [ file [ ... ] ] ]
That is, zero or more optional parameters followed by:
  1. The name of the file that contains the old text to look for;
  2. The name of the file that contains the the new text to replace it with;
  3. The name(s) of one or more files where the text should be replaced.
The third parameter (and any that follow it) can be regular filenames, or “wildcards” such as *.c, meaning “all files whose names end in “.c” If the wildcard matches names of files that are not text files, Replacetextblock automatically skips them.

Be very careful not to omit the oldtext or newtext arguments. If you start the script with something like "replacetext *.txt" it will treate the first file that matches the wildcard as the oldtext file and the second as the newtext file, which is probably not what you intended. There's no way the script could prevent this. (Well, I suppose it would be possible to have -oldtext:xxx and -newtext:yyy options but let's leave that for version 2).

Options start with a hyphen ('-'). The options are:

-help
Tells the script to print a help ("usage") message.
-quiet
This tells the script to run without printing any progress messages. If there are any serious errors, however, appropriate messages will still show up.
-debug
This says to print additional progress messages that are not normally seen, which might be helpful.
-changeall
Normally Replacetextblock replaces only the first occurrence of the "oldtext" in each file. This option tells it to replace all occurrences.
-nobackup
Tells Replacetextblock not to make backups of the files that were changed.
-nopatterns
This tells the script to treat the "oldtext" as literal text and compare it literally with the contents of each file, rather than doing any pattern matching as described above. This is appropriate when the target files don't have any variations in the searched-for text, and it means you don't have to apply any quoting in the "oldtext" file.
-except:xxx
This tells the script not to process the file named xxx or, if xxx is a wildcard, not to process any file whose name matches it. If xxx is a wildcard, its wildcard characters must be quoted to suppress expansion by the Unix shell where you are giving the command. Example:
replacetextblock -except:\*-old.\* oldtext newtext *.[ch]

Filenames should not start with hyphen; otherwise the script will think they are options. If you need to process a group of files where one or more of the names might start with a hyphen, use this notation:

replacetextblock -except:\*-old.\* oldtext newtext ./*.[ch]
that is, prefix the filename or wildcard with “./”.

Suggested use

The Replacetextblock script is conservative, in that it doesn't destroy anything unless you go out of your way to tell it to. Suppose you have a directory full of important files you need to change. Obviously, you should back them up first. But even if you don't, if you follow these steps, you should be able to avoid disaster:
  1. Do your first Replacetextblock run with -debug. This shows you what the results would be, but does not actually update the files. Instead, for every file that would be updated, xxx, it creates an xxx.new file that you can look at to make sure it's what you wanted. Then you can delete the *.new files.

  2. Do your next run without -debug. The files are replaced, but for each file xxx that was changed, the original is copied to xxx.backup. If the files are source code, you should try compiling them; if they are web-page sources, try looking at them in a Web browser (etc).

  3. Once you are certain that the changes were correct, you can move the .backup files somewhere else or just delete them.

Getkermitscript / The Kermit Project / kermit@kermitproject.org