Finding a specific text string in a source file is a common task for any programmer. You may need to find a method or variable in one of your own source files, or you may want to search third-party source files and headers for a certain text string. Regardless of what you're searching for, you need a quick and easy way to perform the search.
C++Builder comes with a command-line utility called GREP.EXE (commonly called Grep) that lets you search for text in files. You can use Grep to perform simple text searches as well as more complex searches. In addition, you can search across directories and look in many different file types. In this article, we'll explain how to get the most out of Grep. We'll describe how to search for text in files, how to capture the Grep output to a text file, and how to perform more complex searches.
If you're a new C++Builder user, you may not see the need to search files for text. However, over time you'll come to understand the benefit of searching source files for a particular text string. For example, I sometimes wonder how a certain method works in VCL, but I can never remember which VCL source files contain which methods. It doesn't matter, though, because I can Grep the VCL source for the method I want to inspect. Let's take a look at how you use Grep.
The syntax for Grep is fairly straightforward:
grep [options] searchstring filestosearchHere's a real-world example that illustrates this syntax. Let's say you want to search all C++ source files in the current directory for the text string TForm. You first open a command prompt box, then switch to the directory containing the files you wish to search and type the following at the command line:
grep TForm *.cppWhen you press [Enter], Grep will search all files with a CPP extension and list any matches it finds. For example, this search resulted in the following output on my system:
File SPMain.cpp: : TForm(Owner) else TForm::Dispatch(Message); File SPAbout.cpp: : TForm(Owner) File RegMain.cpp: : TForm(Owner) File MsgTBar.cpp: : TForm(Owner) File MsgMain.cpp: : TForm(Owner) // checked then we just call TForm::Dispatch() and TForm::Dispatch(Message);If Grep finds any matches, it displays in the console window the name of the file containing the search string, followed by any occurrences of the string. As you can see, Grep displays the entire line containing the matched string. (Note that Grep is a search utility only--you can't use it to search and replace text in files.)
Also, if you're searching for a multiple-word phrase, you must enclose the phrase in double quotes (single quotes won't work). For example, let's say you want to search all C++ source files for the text = new. The command line will look like this:
grep "= new" *.cppIf you typed this line and failed to use the quotes, then Grep would generate a listing of all lines with an equal sign--it would ignore the new part of the string.
You can search multiple file types by separating each file type with a space. Suppose you want to find all occurrences of TForm in both your source files and your headers. In this case, you'll type the following at the command line:
grep TForm *.cpp *.hGrep will search both CPP and H files and display all lines that contain the search text.
Table A: Grep regular expressions
| Expression | Description |
| ^ | Start of line |
| $ | End of line |
| . | Any character |
| \ | Quote next character |
| * | Match zero or more |
| + | Match one or more |
| [az1-3] | Match a, z, and 1 through 3 |
| [^az] | Match all but a and z |
A picture is always worth a thousand words, so let's look at how you might use some of these expressions. For our first example, let's say you want to find the variable x--but only where it starts a line of code. In this case, you'll execute Grep with this command line:
grep ^x *.cppThe circumflex (^) tells Grep to show all occurrences of the variable x, but only if that variable occurs at the beginning of the line.
The end-of-line character ($) works in a similar way. For example, if you want to find the variable x anywhere it occurs at the end of a line, you can use the following statement:
grep x;$ *.cppThe backslash character (\) tells Grep to treat the character following the backslash not as a regular expression character, but rather as a literal character. For example, let's suppose you want to search for all occurrences of MyString., to find any places where you called a method of the MyString object. You'd probably first try this line:
grep MyString. *.cppThe problem is, the period is a regular-expression character that matches any character in the file you're searching. So, Grep will find matches for MyString followed by any character. Consequently, you need to tell Grep that you want to search for a literal period and not to use the period as a special character. The correct syntax is as follows:
grep MyString\. *.cppNotice the backslash before the period. Now Grep will report only occurrences of MyString followed by a period. Remember, you'll also need the backslash when the search string includes square brackets ([ ]) or parentheses (( )).
Let's look at one more example of a regular expression search. Say you want to search for a class named TMyBigLongClassName. Rather than typing in the entire class name, you can use the + regular expression character--this character is similar to the asterisk wildcard used in filenames. For example, this statement
grep TMyBig+ *.cppwill tell Grep to search for words beginning with TMyBig and ending with any number of characters.
Using regular expressions can help narrow your searches so you receive more meaningful search results. Note that you can also use regular expressions in the C++Builder code editor's Find Text and Replace Text dialog boxes. By using regular expressions in your find and replace operations, you can more quickly and more accurately deal with text in your source code units.
Table B: Commonly used Grep options
| Option | Description |
| -d | Search subdirectories |
| -i | Ignore case |
| -n | List line numbers |
| -r | Regular-expression search (on by default) |
| -z | Verbose output |
Most of the command-line options are self-explanatory. To search the current directory and all subdirectories for a given string, you use the -d option as follows:
grep -d TForm *.cppTo add to this example, you can also opt to perform a case-insensitive search by using the -i switch. In that case, the command line will look like this:
grep -d -i tform *.cppTo remove an option from the search, add a minus sign after the option. For example, regular expressions are on by default. If you want to perform a search without using regular expressions, you can use a line like the following:
grep -r- (MyString. *.cppThis example turns off regular expressions, thereby allowing Grep to treat the parenthesis and the period as literal characters.
For a complete list of Grep command-line options, look for the Grep topic in the help file BCBTOOLS. Note that the -u option, which is supposed to let you set the default Grep options, has no effect with the version of Grep that comes with C++Builder.
Sometimes, though, you'll want to capture the results of a Grep search to a file. You can do that easily by redirecting the output of the console window to a text file. To redirect the Grep output to a file, simply follow the Grep command line with a closing angle bracket (>) followed by the name of a text file. For example, the line
grep -d TForm *.cpp > results.txtwill place the results of the search, if any, in a file called RESULTS.TXT. (When you redirect output to a text file, Grep doesn't display any search matches in the console window. You'll have to open the text file to see the results.)
Once you've redirected the search results to a text file, you can open the file with any text editor and view the results. Note that the redirection is a function of the operating system and not a function of Grep itself: You can redirect the output from any of the C++Builder command-line utilities, such as TDUMP.EXE.
In a similar vein, you can use the Clipboard to copy text directly from the command prompt window. Next month, we'll discuss how you can use the Clipboard with command prompt boxes and offer some other handy command prompt tips.
Many current development environments contain a built-in Grep. When properly implemented, as in Borland C++ 5.0, the integrated Grep is even more helpful. Unfortunately, C++Builder doesn't have a built-in Grep utility, although rumor has it that the next version of C++Builder will have one.
In the meantime, you can continue to run Grep from the command line, or you might want to look at third-party Grep utilities. One of the most popular Grep add-ons for Delphi--and now for C++Builder--is part of John Howe's Triplex suite. Triplex is a collection of experts for Delphi and C++Builder, one of which is a Grep Expert. For the moment, Triplex is freeware and is available for download at ds.dial.pipex.com/triplex. You'll definitely want to take a look.
Kent Reisdorph is a editor of the C++Builder Developer's Journal as well as director of systems and services at TurboPower Software Company, and a member of TeamB, Borland's volunteer online support group. He's the author of Teach Yourself C++Builder in 21 Days and Teach Yourself C++Builder in 14 Days. You can contact Kent at editor@bridgespublishing.com.