[MR/2 ICE - Delivering the electronic mail features of the future, today. (click here)]

The REXX Files- by Dr. Dirk Terrell


REXX is a great choice of language if you need to process text files. Since all variables in REXX are treated as strings, it makes sense that the language would have some very useful functions for manipulating them. This month, let's look at some of these string-handling functions.

One need that arises quite often when processing strings is the need to know how long the string is. That is, what is the length of the string? In REXX, you use the LENGTH function:

string_length=LENGTH(string)

where string_length is the length of the string in bytes, and string is the string whose length we need to know. Nothing too complicated there.

Another common need is to know whether or not a string is contained within another string, and if it is, at what position. The Pos function returns the first position of one string within another. If the first string is not found in the second, the function returns 0 (zero).

For a concrete example, let's write a program that scans a CONFIG.SYS file and looks for a particular string that we specify. For safety, let's copy the contents of CONFIG.SYS to CONFIG.TST and use that file rather than mess with CONFIG.SYS directly.

/* Scans the CONFIG.SYS file for a specified string */
Parse Arg Target
Target_Uppercase=Translate(Target)

/* Exit if the user didn't supply a string for the search */
If Target="" then Do
   Say " "
   Say "You must enter a string to find..."
   Exit
end /* do */

/* Copy CONFIG.SYS to CONFIG.TST for safety
   Assumes that CONFIG.SYS is in the root directory of the C: drive
   change as appropriate
*/
"copy c:\config.sys config.tst"

/* Exit if we can't find the file */
if rc<>0 then Do
   Say " "
   Say "Could not find CONFIG.SYS!"
   Exit
end /* do */
At this point we have copied the contents of CONFIG.SYS to CONFIG.TST. Now we can read in the contents of CONFIG.TST with the I/O functions that we looked at last month:
/* 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")
Exit
The variable Current_Line_Number is a counter that is incremented each time we read a line from the file. We are using Linein to read a line and store the contents in a_line. But what is the purpose of this Translate function? Translate is used to translate characters in a string to other characters. For example if you wanted to replace all instances of the letter A with B in "FOOBAR", you would use Translate:

New_String=Translate("FOOBAR","B","A")

The variable New_String would have the value "FOOBBR" after the above function call. Note that this function (and all string functions in REXX for that matter) is case-sensitive. Making the above call like this:

New_String=Translate("foobar","B","A")

would result in New_String's value being "foobar" (i.e., no change) because there are no capital A's in the string. The default parameters for Translate are such that calling it with just the string as the argument results in the string being converted to uppercase. This is handy in situations like the one we have here -- comparing strings in a case-insensitive manner (i.e. you want "FOOBAR" and "foobar" to match). In the above code, we use the call:

Test_Line=Translate(a_line)

to convert the contents of a_line to uppercase. We then compare the result to the uppercase version of the string we are searching for with the Pos function:

Found=Pos(Target_Uppercase,Test_Line)
If Found<>0 then Do
   Say Current_Line_Number a_line
end /* do */
If the value returned by the call to Pos is not 0 (zero), it means that our target string was found in this line of the file. The program prints out the line number (variable Current_Line_Number) and then the contents of a_line.

What happens when a string appears multiple times in another? For example, what happens if we search for O in "FOOBAR"? Pos returns the position of the first instance of the string, so:

location=Pos("O","FOOBAR")

would set location equal to 2 since the first instance of O is at character number 2. The more general calling form for Pos allows you to specify where the search should start:

location=Pos("O","FOOBAR",1)

This call would return the same result. But the call:

location=Pos("O","FOOBAR",3)

would return 3 because we are telling Pos to start at character number 3. If we do this:

location=Pos("O","FOOBAR",4)

then the value 0 will be returned because there are no instances of the letter O in "FOOBAR" after the fourth character.

The LastPos function is similar to the Pos function, but, as its name suggests, it returns the position of the last instance of the target string. So, the call:

location=LastPos("O","FOOBAR")

would return 3 because character number 3 is the last time O appears in "FOOBAR". Like Pos, you can specify the starting point for the search by passing it as the third parameter in the function call.

The sample code this month is the program that scans the CONFIG.SYS file for a specified string and prints out the lines that contain the string. Try modifying it so that the user could specify a command line switch, say -s, that would allow the search to be case-sensitive. Next month we'll continue our exploration of the string handling functions in REXX, by extending the program to actually modify the contents of the file.


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.

[Index]  [ Previous] - [Feedback] - [Next ]

[Our Sponsor: Mensys - The one place to go in Europe for all OS/2 Warp software.]


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

Copyright © 1997 - Falcon Networking