ش
Shell Variables
The Bash, Korn, and Z shells described previously are actually types of shells. A shell, by definition, is an interpretive environment within which you execute commands. You could have many environments running at the same time, either of the same type or of different types of shells. These interpretive environments are referred to as shells. So you could have several shells running at the same time that are of the Bash shell type.
Within each shell, you could enter and execute commands. You can further enhance the capabilities of a shell using shell variables. With a shell variable, you can hold data that you could reference over and over again as you execute different commands within a given shell. For example, you could define a shell variable to hold the name of complex filename. Instead of retyping the filename in different commands, you could reference it with the shell variable.
You define variables within a shell, and such variables are known as shell variables. Many different shells exist. Some utilities, such as the Mail utility, have their own shells with their own shell variables. You can also create your own shell using what are called shell scripts. You have a user shell that becomes active as soon as you log in. This is often referred to as the login shell. Special system variables are defined within this login shell. Shell variables can also be used to define a shell's environment, as described in Chapter 9.
|
Note |
Shell variables exist as long as your shell is active—that is, until you exit the shell. For example, logging out will exit the login shell. When you log in again, any variables you may need in your login shell must be defined again. |
Definition and Evaluation of Variables: =, $, set, unset
You define a variable in a shell when you first use the variable's name. A variable's name may be any set of alphabetic characters, including the underscore. The name may also include a number, but the number cannot be the first character in the name. A name may not have any other type of character, such as an exclamation point, an ampersand, or even a space. Such symbols are reserved by the shell for its own use. Also, a variable name may not include more than one word. The shell uses spaces on the command line to distinguish different components of a command such as options, arguments, and the name of the command.
You assign a value to a variable with the assignment operator, =. You type the variable name, the assignment operator, and then the value assigned. Do not place any spaces around the assignment operator. The assignment operation poet = Virgil, for example, will fail. (The C shell has a slightly different type of assignment operation.) You can assign any set of characters to a variable. In the next example, the variable poet is assigned the string Virgil:
$ poet=Virgil
Once you have assigned a value to a variable, you can then use the variable name to reference the value. Often you use the values of variables as arguments for a command. You can reference the value of a variable using the variable name preceded by the $ operator. The dollar sign is a special operator that uses the variable name to reference a variable's value, in effect evaluating the variable. Evaluation retrieves a variable's value, usually a set of characters. This set of characters then replaces the variable name on the command line. Wherever a $ is placed before the variable name, the variable name is replaced with the value of the variable. In the next example, the shell variable poet is evaluated and its contents, Virgil, are then used as the argument for an echo command. The echo command simply echoes or prints a set of characters to the screen.
$ echo $poet
Virgil
You must be careful to distinguish between the evaluation of a variable and its name alone. If you leave out the $ operator before the variable name, all you have is the variable name itself. In the next example, the $ operator is absent from the variable name. In this case, the echo command has as its argument the word "poet", and so prints out "poet":
$ echo poet
poet
The contents of a variable are often used as command arguments. A common command argument is a directory pathname. It can be tedious to retype a directory path that is being used over and over again. If you assign the directory pathname to a variable, you can simply use the evaluated variable in its place. The directory path you assign to the variable is retrieved when the variable is evaluated with the $ operator. The next example assigns a directory pathname to a variable and then uses the evaluated variable in a copy command. The evaluation of ldir (which is $ldir) results in the pathname /home/chris/letters. The copy command evaluates to cp myletter /home/chris/letters.
$ ldir=/home/chris/letters
$ cp myletter $ldir
You can obtain a list of all the defined variables with the set command. If you decide you do not want a certain variable, you can remove it with the unset command. The unset command undefines a variable.
Shell Variables
The Bash, Korn, and Z shells described previously are actually types of shells. A shell, by definition, is an interpretive environment within which you execute commands. You could have many environments running at the same time, either of the same type or of different types of shells. These interpretive environments are referred to as shells. So you could have several shells running at the same time that are of the Bash shell type.
Within each shell, you could enter and execute commands. You can further enhance the capabilities of a shell using shell variables. With a shell variable, you can hold data that you could reference over and over again as you execute different commands within a given shell. For example, you could define a shell variable to hold the name of complex filename. Instead of retyping the filename in different commands, you could reference it with the shell variable.
You define variables within a shell, and such variables are known as shell variables. Many different shells exist. Some utilities, such as the Mail utility, have their own shells with their own shell variables. You can also create your own shell using what are called shell scripts. You have a user shell that becomes active as soon as you log in. This is often referred to as the login shell. Special system variables are defined within this login shell. Shell variables can also be used to define a shell's environment, as described in Chapter 9.
|
Note |
Shell variables exist as long as your shell is active—that is, until you exit the shell. For example, logging out will exit the login shell. When you log in again, any variables you may need in your login shell must be defined again. |
Definition and Evaluation of Variables: =, $, set, unset
You define a variable in a shell when you first use the variable's name. A variable's name may be any set of alphabetic characters, including the underscore. The name may also include a number, but the number cannot be the first character in the name. A name may not have any other type of character, such as an exclamation point, an ampersand, or even a space. Such symbols are reserved by the shell for its own use. Also, a variable name may not include more than one word. The shell uses spaces on the command line to distinguish different components of a command such as options, arguments, and the name of the command.
You assign a value to a variable with the assignment operator, =. You type the variable name, the assignment operator, and then the value assigned. Do not place any spaces around the assignment operator. The assignment operation poet = Virgil, for example, will fail. (The C shell has a slightly different type of assignment operation.) You can assign any set of characters to a variable. In the next example, the variable poet is assigned the string Virgil:
$ poet=Virgil
Once you have assigned a value to a variable, you can then use the variable name to reference the value. Often you use the values of variables as arguments for a command. You can reference the value of a variable using the variable name preceded by the $ operator. The dollar sign is a special operator that uses the variable name to reference a variable's value, in effect evaluating the variable. Evaluation retrieves a variable's value, usually a set of characters. This set of characters then replaces the variable name on the command line. Wherever a $ is placed before the variable name, the variable name is replaced with the value of the variable. In the next example, the shell variable poet is evaluated and its contents, Virgil, are then used as the argument for an echo command. The echo command simply echoes or prints a set of characters to the screen.
$ echo $poet
Virgil
You must be careful to distinguish between the evaluation of a variable and its name alone. If you leave out the $ operator before the variable name, all you have is the variable name itself. In the next example, the $ operator is absent from the variable name. In this case, the echo command has as its argument the word "poet", and so prints out "poet":
$ echo poet
poet
The contents of a variable are often used as command arguments. A common command argument is a directory pathname. It can be tedious to retype a directory path that is being used over and over again. If you assign the directory pathname to a variable, you can simply use the evaluated variable in its place. The directory path you assign to the variable is retrieved when the variable is evaluated with the $ operator. The next example assigns a directory pathname to a variable and then uses the evaluated variable in a copy command. The evaluation of ldir (which is $ldir) results in the pathname /home/chris/letters. The copy command evaluates to cp myletter /home/chris/letters.
$ ldir=/home/chris/letters
$ cp myletter $ldir
You can obtain a list of all the defined variables with the set command. If you decide you do not want a certain variable, you can remove it with the unset command. The unset command undefines a variable.
Control Structures
You can control the execution of Linux commands in a shell script with control structures. Control structures allow you to repeat commands and to select certain commands over others. A control structure consists of two major components: a test and commands. If the test is successful, then the commands are executed. In this way, you can use control structures to make decisions as to whether commands should be executed.
There are two different kinds of control structures: loops and conditions. A loop repeats commands, whereas a condition executes a command when certain conditions are met. The BASH shell has three loop control structures: while, for, and for-in. There are two condition structures: if and case. The control structures have as their test the execution of a Linux command. All Linux commands return an exit status after they have finished executing. If a command is successful, its exit status will be 0. If the command fails for any reason, its exit status will be a positive value referencing the type of failure that occurred. The control structures check to see if the exit status of a Linux command is 0 or some other value. In the case of the if and while structures, if the exit status is a zero value, then the command was successful and the structure continues.
Test Operations
With the test command, you can compare integers, compare strings, and even perform logical operations. The command consists of the keyword test followed by the values being compared, separated by an option that specifies what kind of comparison is taking place. The option can be thought of as the operator, but it is written, like other options, with a minus sign and letter codes. For example, -eq is the option that represents the equality comparison. However, there are two string operations that actually use an operator instead of an option. When you compare two strings for equality you use the equal sign, =. For inequality you use !=. Table 8-6 lists some of the commonly used options and operators used by test. The syntax for the test command is shown here:
test value -option value
test string = string
|
Integer Comparisons |
Function |
|
-gt |
Greater-than |
|
-lt |
Less-than |
|
-ge |
Greater-than-or-equal-to |
|
-le |
Less-than-or-equal-to |
|
-eq |
Equal |
|
-ne |
Not-equal |
|
String Comparisons |
|
|
-z |
Tests for empty string |
|
= |
Equal strings |
|
!= |
Not-equal strings |
|
Logical Operations |
|
|
-a |
Logical AND |
|
-o |
Logical OR |
|
! |
Logical NOT |
|
File Tests |
|
|
-f |
File exists and is a regular file |
|
-s |
File is not empty |
|
-r |
File is readable |
|
-w |
File can be written to, modified |
|
-x |
File is executable |
|
-d |
Filename is a directory name |
In the next example, the user compares two integer values to see if they are equal. In this case, you need to use the equality option, -eq. The exit status of the test command is examined to find out the result of the test operation. The shell special variable $? holds the exit status of the most recently executed Linux command.
$ num=5
$ test $num -eq 10
$ echo $?
1
Instead of using the keyword test for the test command, you can use enclosing brackets. The command test $greeting = "hi" can be written as
$ [ $greeting = "hi" ]
Similarly, the test command test $num -eq 10 can be written as
$ [ $num -eq 10 ]
The brackets themselves must be surrounded by white space: a space, TAB, or ENTER. Without the spaces, it would be invalid.
Conditional Control Structures
The BASH shell has a set of conditional control structures that allow you to choose what Linux commands to execute. Many of these are similar to conditional control structures found in programming languages, but there are some differences. The if condition tests the success of a Linux command, not an expression. Furthermore, the end of an if-then command must be indicated with the keyword fi, and the end of a case command is indicated with the keyword esac. The condition control structures are listed in Table 8-7.
The if structure places a condition on commands. That condition is the exit status of a specific Linux command. If a command is successful, returning an exit status of 0, then the commands within the if structure are executed. If the exit status is anything other than 0, then the command has failed and the commands within the if structure are not executed. The if command begins with the keyword if and is followed by a Linux command whose exit condition will be evaluated. The keyword fi ends the command. The elsels script in the next example executes the ls command to list files with two different possible options, either by size or with all file information. If the user enters an s, files are listed by size; otherwise, all file information is listed.
|
Condition Control Structures: |
Function |
|
if command then |
if executes an action if its test command is true. |
|
if command then |
if-else executes an action if the exit status of its test command is true; if false, then the else action is executed. |
|
if command then |
elif allows you to nest if structures, enabling selection among several alternatives; at the first true if structure, its commands are executed and control leaves the entire elif structure. |
|
case string in |
case matches the string value to any of several patterns; if a pattern is matched, its associated commands are executed. |
|
command && command |
The logical AND condition returns a true 0 value if both commands return a true 0 value; if one returns a non-zero value, then the AND condition is false and also returns a non-zero value. |
|
command || command |
The logical OR condition returns a true 0 value if one or the other command returns a true 0 value; if both commands return a non-zero value, then the OR condition is false and also returns a non-zero value. |
|
! command |
The logical NOT condition inverts the return value of the command. |
|
Loop Control Structures: |
|
|
while command |
while executes an action as long as its test command is true. |
|
until command |
until executes an action as long as its test command is false. |
|
for variable in list-values |
for-in is designed for use with lists of values; the variable operand is consecutively assigned the values in the list. |
|
for variable |
for is designed for reference script arguments; the variable operand is consecutively assigned each argument value. |
|
select string in item-list |
select creates a menu based on the items in the item-list; then it executes the command; the command is usually a case. |
|
|
echo Enter s to list file sizes,
echo otherwise all file information is listed.
echo -n "Please enter option: "
read choice
if [ "$choice" = s ]
then
ls -s
else
ls -l
fi
echo Good-bye
|
|
A run of the program follows:
$ elsels
Enter s to list file sizes,
otherwise all file information is listed.
Please enter option: s
total 2
1 monday 2 today
$
Loop Control Structures
The while loop repeats commands. A while loop begins with the keyword while and is followed by a Linux command. The keyword do follows on the next line. The end of the loop is specified by the keyword done. The Linux command used in while structures is often a test command indicated by enclosing brackets.
The for-in structure is designed to reference a list of values sequentially. It takes two operands—a variable and a list of values. The values in the list are assigned one by one to the variable in the for-in structure. Like the while command, the for-in structure is a loop. Each time through the loop, the next value in the list is assigned to the variable. When the end of the list is reached, the loop stops. Like the while loop, the body of a for-in loop begins with the keyword do and ends with the keyword done. The cbackup script makes a backup of each file and places it in a directory called sourcebak. Notice the use of the * special character to generate a list of all filenames with a .c extension.
|
|
for backfile in *.c
do
cp $backfile sourcebak/$backfile
echo $backfile
done
|
|
A run of the program follows:
$ cbackup
io.c
lib.c
main.c
$
The for structure without a specified list of values takes as its list of values the command line arguments. The arguments specified on the command line when the shell file is invoked become a list of values referenced by the for command. The variable used in the for command is set automatically to each argument value in sequence. The first time through the loop, the variable is set to the value of the first argument. The second time, it is set to the value of the second argument.
Filters and Regular Expressions
Filters are commands that read data, perform operations on that data, and then send the results to the standard output. Filters generate different kinds of output, depending on their task. Some filters generate information only about the input, other filters output selected parts of the input, and still other filters output an entire version of the input, but in a modified way. Some filters are limited to one of these, while others have options that specify one or the other. You can think of a filter as operating on a stream of data—receiving data and generating modified output. As data is passed through the filter, it is analyzed, screened, or modified.
The data stream input to a filter consists of a sequence of bytes that can be received from files, devices, or the output of other commands or filters. The filter operates on the data stream, but it does not modify the source of the data. If a filter receives input from a file, the file itself is not modified. Only its data is read and fed into the filter.
The output of a filter is usually sent to the standard output. It can then be redirected to another file or device, or piped as input to another utility or filter. All the features of redirection and pipes apply to filters. Often data is read by one filter and its modified output piped into another filter.
|
Note |
Data could easily undergo several modifications as it is passed from one filter to another. However, it is always important to realize the original source of the data is never changed. |
Many utilities and filters use patterns to locate and select specific text in your file. Sometimes, you may need to use patterns in a more flexible and powerful way, searching for several different variations on a given pattern. You can include a set of special characters in your pattern to enable a flexible search. A pattern that contains such special characters is called a regular expression. Regular expressions can be used in most filters and utilities that employ pattern searches such as sed, awk, grep, and egrep.
|
Tip |
Although many of the special characters used for regular expressions are similar to the shell file expansion characters, they are used in a different way. Shell file expansion characters operate on filenames. Regular expressions search text. |
You can save the output of a filter in a file or send it to a printer. To do so, you need to use redirection or pipes. To save the output of a filter to a file, you redirect it to a file using the redirection operation, >. To send output to the printer, you pipe the output to the lpr utility, which then prints it. In the next command, the cat command pipes its output to the lpr command, which then prints it.
$ cat complist | lpr
All filters accept input from the standard input. In fact, the output of one filter can be piped as the input for another filter. Many filters also accept input directly from files, however. Such filters can take filenames as their arguments and read data directly from those files.
Searching Files: grep
The grep and fgrep filters search the contents of files for a pattern. They then inform you of what file the pattern was found in and print the lines in which it occurred in each file. Preceding each line is the name of the file in which the line is located. grep can search for only one pattern, whereas fgrep can search for more than one pattern at a time.
The grep filter takes two types of arguments. The first argument is the pattern to be searched for; the second argument is a list of filenames, which are the files to be searched. You enter the filenames on the command line after the pattern. You can also use special characters, such as the asterisk, to generate a file list.
$ grep pattern filenames-list
If you want to include more than one word in the pattern search, you enclose the words within single quotation marks. This is to quote the spaces between the words in the pattern. Otherwise, the shell would interpret the space as a delimiter or argument on the command line, and grep would try to interpret words in the pattern as part of the file list. In the next example, grep searches for the pattern "text file":
$ grep 'text file' preface
A text file in Unix
text files, changing or
If you use more than one file in the file list, grep will output the name of the file before the matching line. In the next example, two files, preface and intro, are searched for the pattern "data". Before each occurrence, the filename is output.
$ grep data preface intro
preface: data in the file.
intro: new data
As mentioned earlier, you can also use shell file expansion characters to generate a list of files to be searched. In the next example, the asterisk file expansion character is used to generate a list of all files in your directory. This is a simple way of searching all of a directory's files for a pattern.
$ grep data *
The special characters are often useful for searching a selected set of files. For example, if you want to search all your C program source code files for a particular pattern, you can specify the set of source code files with *.c. Suppose you have an unintended infinite loop in your program and you need to locate all instances of iterations. The next example searches only those files with a .c extension for the pattern "while" and displays the lines of code that perform iterations:
$ grep while *.c
Regular Expressions
Regular expressions enable you to match possible variations on a pattern, as well as patterns located at different points in the text. You can search for patterns in your text that have different ending or beginning letters, or you can match text at the beginning or end of a line. The regular expression special characters are the circumflex, dollar sign, asterisk, period, and brackets: ^, $, *, ., []. The circumflex and dollar sign match on the beginning and end of a line. The asterisk matches repeated characters, the period matches single characters, and the brackets match on classes of characters. See Table 8-8 for a listing of the regular expression special characters.
|
Character |
Match |
Operation |
|
^ |
Start of a line |
References the beginning of a line |
|
$ |
End of a line |
References the end of a line |
|
. |
Any character |
Matches on any one possible character in a pattern |
|
* |
Repeated characters |
Matches on repeated characters in a pattern |
|
[] |
Classes |
Matches on classes of characters (a set of characters) in the pattern |
Suppose you want to use the long-form output of ls to display just your directories. One way to do this is to generate a list of all directories in the long form and pipe this list to grep, which can then pick out the directory entries. You can do this by using the ^ special character to specify the beginning of a line. Remember, in the long-form output of ls, the first character indicates the file type. A d represents a directory, a l represents a symbolic link, and an a represents a regular file. Using the pattern '^d', grep will match only on those lines beginning with a d.
$ ls -l | grep '^d'
drwxr-x--- 2 chris 512 Feb 10 04:30 reports
drwxr-x--- 2 chris 512 Jan 6 01:20 letters

