| the REXX Files | - by Dr. Dirk Terrell

  ast month we began looking at the string-handling capabilities of REXX and the example program scanned CONFIG.SYS for a specified string. Let's continue with that theme this month by modifying the program to replace the specified string with another one. Let's name the REXX file REPLCF.CMD.

  First we'll have to modify the input of the program because we now need to specify two strings -- the target string and the string with which we want to replace the target string. There are several ways to accomplish this. Let's assume that if two strings are passed to the program, the first is the target and the second is the replacement. For example:

  REPLCFG Windows OS/2

  should replace all instances of Windows with OS/2. But what if the target and/or replacement string are phrases rather than words? In that case, we have to have a way of letting the program know where the target ends and where the replacement begins. There are all sorts of ways to do this, but arguably the most intuitive way would be to enclose each one in quotes, so let's do it that way. So, the command:

  REPLCFG "Windows crashes too often." "OS/2 is stable."

  should replace all instances of "Windows crashes too often." with "OS/2 is stable." (minus the quotes).

  To execute the above specification, first we read in the command line parameters using PARSE ARG as usual:

  PARSE ARG Input_Parameters

  Now we need to find out how many parameters have been passed to the program. If fewer than two parameters were passed, we should print an error message and exit. If two parameters were passed, then we should assume that the first is the target and the second is the replacement. If more than two are passed, then we should use the quotes to separate the target and the replacement. The WORDS function will return the number of words in a string (i.e., the number of space delimited strings). Since we have multiple possibilities, let's use SELECT to handle the decision structure. The following code handles the input:

      /* Scan config.sys for a string and replace it with another one */

      Parse Arg Input_Parameters
      Test=Words(Input_Parameters)
      Select
         when Test<2 then do
            say ""
            say "You must enter a target and a replacement string."
            say ""
            exit
         end /* do */
         when test>2 then Do
            Parse Var Input_Parameters '"' Target '"' '"' Replacement '"'
         end /* do */
      otherwise /* If it falls through to here, we must have 2 input strings */
            Parse Var Input_Parameters Target Replacement
      end  /* select */

  You may wonder about all those quotes in the PARSE statement when the input strings are phrases. They are double quotes (") inside single quotes ('). In REXX either single or double quotes can be used around strings, and since we are using double quotes in the input, we parse for them and use single quotes to surround them in the program. If we wanted to use single quotes for input, we would just switch them around in the program. We could even get really fancy and allow the user to use either type of quotation mark. I'll leave that as an exercise you can try.

  Now that we have the input, we scan the CONFIG.SYS file for the target string (using the safe method of copying it to CONFIG.TST like we did last month). As we did last month, let's make the search case-insensitive since entries in CONFIG.SYS are generally not case sensitive. To do this we use UPPERCASE to convert all the strings to uppercase before comparing them. Let's take the loop we used last month and modify it a bit. Here is the old code:

      /* Now search the file for the target string */
      Current_Line_Number=0
      Do While Lines("CONFIG.TST")
         a_line=Linein("CONFIG.TST")
         Current_Line_Number=Current_Line_Number+1
         Test_Line=Translate(a_line)
         Found=Pos(Target_Uppercase,Test_Line)
         If Found<>0 then Do
            Say Current_Line_Number a_line
         end /* do */
      end /* do */
      rc=Stream("CONFIG.TST","C","Close")

  Where we need to do some additional work is in the If Found ... section, so let's write new code to paste there.

  If we find the target string in a particular line, we need to replace it with the replacement string. If the target string isn't in the line, we should just leave the line as it is.

  Let's call the new file CONFIG.NEW. Remember that REXX will append text to a file if the file already exists, so we must be sure to delete CONFIG.NEW before we start writing to it. Use POS to search each line for the target string. Recall that POS returns the position of the first occurrence of the target string. We will have to make sure that we replace multiple occurrences of the target string if they exist too. To accomplish this, we will use POS within a WHILE loop to make sure we get all of the occurrences of the target string. Within that loop, we will split the input line at the first occurrence of the target string, and insert the replacement string in place of the target string. Here is the code:

      Do While Lines("CONFIG.TST")
         a_line=Linein("CONFIG.TST")
         Current_Line_Number=Current_Line_Number+1
         Test_Line=Translate(a_line)
         Found=Pos(Target_Uppercase,Test_Line)
         If Found<>0 then Do
            Say ""
            Say "Found target in line" Current_Line_Number
            Say a_line
            Call Replace
            Say "The above line was replaced by:"
            Say a_line
         end /* do */
         /* Now we write out a_line to CONFIG.NEW */
         rc=Lineout("CONFIG.NEW",a_line)
      end /* do */

  and the Replace routine is

      Replace:
      /* Replaces all occurrences of the target string in a_line */
      Do While Found<>0
         /* Get the part of the string up to the target */
         First_Part=SubStr(a_line,1,Found-1)
         /*
            Now get the part after the target, the beginning of
            the part of the string after the target is located
            at POS(target,a_line) plus LENGTH(target)
         */
         Last_Location=Found+Target_Length
         Last_Part=SubStr(a_line,Last_Location)
         /* Now put the replacement string in between them */
         a_line=First_Part||Replacement||Last_Part
         /* Now look for the target string again to make sure we get all of them */
         Test_Line=Translate(a_line)
         Found=Pos(Target_Uppercase,Test_Line)
      end /* do */
      Return

  When you run it, the program prints out which lines had the target string, the line before the replacement, and the line after the replacement. The new file is named CONFIG.NEW. You can check the results and if everything is the way you want it, you could copy this file to CONFIG.SYS.

  This kind of program would be useful if you moved all your stuff to a different drive letter or if you changed the name of a directory that appears in many places in your CONFIG.SYS file. Of course, you could just use EPM or some other text editor to do it. But what if you needed to replace the string in hundreds of HTML files? A few modifications to this month's sample program would do the trick, and be much easier than doing it manually with a text editor.

  Dr. Dirk Terrell is an astronomer at the University of Florida specializing in interacting binary stars. His hobbies include cave diving, martial arts, painting and writing OS/2 software such as HTML Wizard.

--

[Our Sponsor: Oberon Software, Inc. - Home of TE/2, TE/2 Pro and other fine OS/2 programs.]

This page is maintained by Falcon Networking. We welcome your suggestions.

Copyright © 1997 - Falcon Networking