During the past 18 months of automating Windows NT Server installations, I discovered an indispensable batch-file utility that UNIX users have always known about—SED. This utility lets me do things that aren't possible or would be more difficult using standard batch-file commands. For example, SED simplifies taking input from a user at a command prompt, retrieving values from text files and assigning them to environment variables, and parsing text files for different stages of an automated installation. Let me introduce you to SED and show you several examples of how this utility can help you make your batch files accomplish more.
What Is SED?
SED is a UNIX editing tool that can now run in DOS and Win32 environments. SED's function is to take a stream of text from a file or the console and manipulate it. Taking input from the console lets you write scripts that prompt the user for input. SED redirects the user's input to a file that your batch files can access.
NT administrators have many advanced scripting languages at their disposal, but SED has one major advantage over these scripting languages—size. The DOS version of SED easily fits on a 3.5" disk. Although SED is available in a Win32 version, I've found that the DOS version is the most useful. The DOS version runs well in DOS and NT, and some Win32 versions of SED don't take user input correctly.
SED commands are case sensitive and their syntax is a bit cryptic, but the time you invest in learning SED rewards you with more capable batch files. To ensure that scripts produce the results you want, you must be careful when writing scripts with SED. Always test SED commands that edit files to make sure they produce the correct results. Administrators can make syntax errors that delete a file's contents or damage system files to the point that their machine stops functioning. The best practice is to make a backup copy of the file before you use SED to edit the file. Figure 1 shows the simplified SED syntax.
Using Search and Replace
Let's start with simple search and replace examples to help you understand the syntax. The SED syntax requires one or more commands, an input source, and an output destination, although whether you supply the input and output parameters is optional. If you don't specify a file as the input source, SED takes the input from the console. If you don't redirect the output to a file, SED sends the results to the console. As you test SED commands, the fact that SED sends the result to the console is very helpful because it saves you from having to look inside an output file. For example, suppose the path to the input file is C:\Temp\ Logon.CMD and the input file contains the following lines:
NET USER X: \\US0031\FILES NET USER Y: \\CA0107\GROUP NET USER Z: \\US0237\USERS
In this batch file, the Net User commands need to be Net Use commands. To fix this error, use the following SED command, which reads the input file, replaces the Net User commands with Net Use commands, and outputs the result to the console:
SED "s/NET USER/NET USE/"
This SED command uses the s function to substitute the string matching a pattern. Three forward slashes (/) always follow the s function, and you place the pattern you want to match between the first and second slashes. You place the string you want SED to substitute between the second and third slashes. Don't forget that SED is always case-sensitive.
Slightly modifying the previous command redirects the output to a new file:SED "s/NET USER/NET USE/" C:\Temp\Logon2.CMD
This command redirects the output to the Logon2.CMD batch file. This step protects the original file from any syntax errors in the SED command that might produce undesirable results.
Next, suppose management decrees a new naming standard for all the servers in your organization. You need to replace your servers' two-character US country code with a three-character USA code. The following SED command reads the original batch file and changes all instances of US to USA:SED "s/US/USA/g"
The g function (i.e., global function), which follows the third slash in this example, instructs SED to replace each occurrence of US, not just the first occurrence. However, this command isn't perfect; it changes the US to USA in all machine names, but it also replaces the US in USERS. To specify which occurrences of US you want to replace, you must modify the previous command:SED "s/\\\\US/\\\\USA/g"
This modification uses four backslashes to tell SED to match the pattern of \\US and replace it with \\USA. The backslash character tells SED to treat the following character literally. To override the special meaning, you must precede all special characters with a backslash.
Taking Input from the User
To show you how to use SED to request input from a user and assign the input value to an environment variable, I'll use the example batch file that Listing 1 shows. The following SED command in this batch file displays a request for user input, then takes the user input:SED e "s/^/SET INPUT=/" e "q" >C:\Temp\Input.bat
To run two commands with one SED statement, use the e option, followed by the commands enclosed in double quotation marks. As the syntax in Figure 1 shows, each command uses an "\[address\] function \[arguments\]" format. The address parameter tells SED which lines of the input stream to apply the function to. You can use many forms to specify an address, including line numbers and pattern matches. Listing 1 doesn't specify an address because you want SED to evaluate each input line. Let's walk through the SED statement in Listing 1 step by step:
- Listing 1 doesn't specify an input file, so SED assumes that the text it needs to process comes from the console. Therefore, when the batch file reaches the SED command, it pauses and waits with a flashing cursor for user input.
- For this example, assume the user inputs Pentium II 450. After the user inputs this value and presses Enter, the SED command processes this line of input. In this command, the s function tells SED to substitute text. The pattern you want SED to match is the beginning of the line, represented by the accent circumflex (^) symbol. This command tells SED to substitute the beginning of the line with SET INPUT=. Thus, SED modifies the user's input to say SET INPUT=Pentium II 450.
- Next, you use the q function to instruct SED to stop searching after it finds the first match, and exit.
- At the end of the SED command, the right angle bracket (>) symbol redirects the output to the C:\Temp\Input.bat file.
You just used SED to create a simple, one-line batch file that contains a user's input. The batch file then executes the Input.bat file that SED created, which assigns the value of Pentium II 450 to the environment variable INPUT. The last lines of Listing 1 delete the Input.bat file and echo the user input back to the console.
Pulling a Value from a Text File
You often need to pull information from text files, especially during automated installations of NT and other software. In this example, you use a slightly more complex pattern match to retrieve the hard disk partition number that NT boots from. NT stores boot information in the boot.ini file in the root directory of the boot disk. The object of this example is to determine the partition number, assign this number to an environment variable, and make automated decisions in a batch file according to the partition number. Listing 2, page 113, shows the contents of the boot.ini file, and Listing 3 shows the batch-file fragment that will extract the partition number.
In this example, you're seeking the number in the third line of boot.ini that is inside the parenthesis following the partition. To simplify the SED commands, Listing 3 uses two statements to retrieve this value. The first SED statement replaces all text in front of the value with the SET command, and the second SED statement removes all text following the number. You can use the f parameter to place multiple commands in a file and run them with one SED statement. This method is preferable after you are more familiar with SED, but it is too complex for this basic introduction to SED. Let's walk through the SED commands that you see in Listing 3:
- The first SED statement uses the left angle bracket (The first command uses the s function to substitute text. The pattern you want SED to match follows the accent circumflex symbol, in this case, lines beginning with default=. The period and asterisk that follow default= tell SED to match any number of characters. The final segment of text you want SED to match is partition(. The command s/^default=.*partition tells SED to match any line that begins with default= and contains partition(, separated by any number of characters.
- After SED finds the matching string, the second segment of the s function tells it to replace the string with SET PARTNUM=.
- The p function follows the last slash of the s function. The p function tells SED to print or duplicate the modified line. You duplicate this line so that you can eventually delete all the original lines of the input and keep only the duplicate lines in the output file.
- The d function comes next in the SED command. When you specify the d function, it deletes each original line of the input file but leaves the duplicate lines that the p function generated.
Only one line in this example matches the pattern. Therefore, the PartNum.out output file contains one line:SET PARTNUM=1)\WINNT
- The second SED command uses the output file from the previous SED command as its input file and uses PartNum.bat as its output file.
- The s function in the second SED command searches for and replaces the ).*$ pattern. This pattern begins with a closing parenthesis, which is the first character that follows the partition number in boot.ini. The period and asterisk wildcard pair tells SED to match any number of characters that follow the closing parenthesis, and the dollar sign specifies the end of the matching line.
- SED finds the matching line and replaces the matching string with a zero-length string, which you identify by placing nothing between the second and third backslashes of the s function. This command results in the following output in the PartNum.bat file:SET PARTNUM=1
The rest of the batch file runs PartNum.bat, which assigns the partition number to the PARTNUM environment variable. The batch file then branches with the GOTO PART%PARTNUM% command to execute the appropriate block of commands.
Editing Text File Contents
You can easily modify a text file's contents. In this example, you change the default boot menu timeout from 30 seconds to 5 seconds. This value follows timeout= on the second line of Listing 2. Listing 4 shows the batch file that modifies the timeout value.
The SED command in Listing 4 uses the s function to match the boot.ini line that starts with timeout=. This function finds and replaces the entire line with timeout=5. The lineCOPY C:\Boot.ini C:\Boot.BAK
makes a backup of the unmodified boot.ini file. This step is very important in case you made a mistake in the SED statement. If the boot.out file that SED generates is empty because of an error, you can use the boot.bak file to revert to a working state.
More About SED
You can download the DOS and Win32 versions of the SED utility from the Windows NT Magazine Web site (http://www.winntmag.com). After you complete the download, place the SED.exe file in one of the directories listed in your machine's search path, such as the C:\winnt directory.
Try SED. With practice and patience, you'll become comfortable with the syntax of this utility. Any NT administrator who is responsible for creating automated installations will find SED to be a valuable tool.