💾 Archived View for gemini.spam.works › mirrors › textfiles › programming › bourne1.txt captured on 2020-10-31 at 14:51:06.
-=-=-=-=-=-=-
UNIX Bourne Shell Programming Developed by: User Liaison Section, D-7131 Denver Office [Name and number removed at author's request] Revision Date: February 7, 1991 I. INTRODUCTION.............................................. v A. Audience............................................. v B. Course Objectives.................................... v C. Course Handout Conventions........................... vi 1. BOURNESHELL OVERVIEW...................................... 1 1.1 What is the BourneShell?............................ 2 1.2 Making a Bourne Shell Script Executable............. 3 1.3 Tracing Mechanisms.................................. 6 Workshop 1............................................... 9 2. USER, SHELL, AND READ-ONLY SHELL VARIABLES................ 11 2.1 User Variables...................................... 11 2.2 Shell Variables..................................... 14 2.2.1 HOME......................................... 14 2.2.2 IFS.......................................... 15 2.2.3 MAIL......................................... 15 2.2.4 MAILPATH..................................... 15 2.2.5 MAILCHECK.................................... 16 2.2.6 PATH......................................... 16 2.2.7 PS1.......................................... 17 2.2.8 PS2.......................................... 17 2.3 Read-Only User Variables............................ 18 2.4 Read-Only Shell Variables........................... 19 2.4.1 Name of the Calling Program.................. 19 2.4.2 Arguments.................................... 19 2.4.3 Shift........................................ 21 2.4.4 Set.......................................... 22 2.4.5 expr......................................... 23 Workshop 2............................................... 27 3. POSITIONAL PARAMETERS..................................... 33 3.1 Reading Input Into a Shell Variable................. 34 3.2 Command Substitution................................ 36 3.3 Comments in BourneShell Scripts..................... 38 3.4 BourneShell Environment - Exporting Variables....... 39 Workshop 3............................................... 41 4. CONTROL CONSTRUCTS:....................................... 45 4.1 Types of Tests Used with Control Constructs:........ 46 4.2 Test on Numeric Values.............................. 47 4.3 Test on Character Strings........................... 47 4.4 Test on File Types.................................. 49 4.5 if then............................................. 50 4.6 if then else........................................ 52 4.7 if then elif........................................ 54 4.8 for................................................. 55 4.9 while............................................... 57 4.10 until.............................................. 58 4.11 case............................................... 60 Workshop 4............................................... 63 5. COMPILING PROGRAMS IN UNIX................................. 67 5.1 "C": Sample Program with a Main and Two Functions in One ................................. 67 5.2 "C": Compiling a Program............................ 69 5.3 "C": Renaming the Executable Module................. 71 5.4 "C": Giving a Name to the Output File............... 72 5.5 "C": Producing an Assembly Listing.................. 73 5.6 "C": Main and Two Functions in Three Separate Source Files.......................................... 74 5.7 "C": Compiling but Not Producing an Executable Module............................................. 75 5.8 FORTRAN: Sample Program a Main and Two Subroutine... 76 5.9 FORTRAN: Compiling a Program........................ 77 5.10 FORTRAN: Renaming the Executable Module............ 79 5.11 FORTRAN: Giving a Name to the Output File.......... 80 5.12 FORTRAN: Producing an Assembly Listing............. 81 5.13 FORTRAN: Main and Two Subroutines in Three Separate Source Files.............................. 82 5.14 FORTRAN: Compiling But Not Producing an Executable Module.................................... 83 5.15 FORTRAN: Compiling Object Files to Produce an Executable Module............................. 84 5.16 COBOL: Sample Program with a Main and Two Subroutines................................. 85 5.17 COBOL: Compiling a Program......................... 86 5.18 COBOL: Running a Program........................... 87 Workshop 5............................................... 89 6. UNIX TOOLS................................................ 95 6.1 Processes........................................... 95 6.2 Executing a Command................................. 95 6.3 Process Identification.............................. 95 6.4 grep: A Pattern Matching Filter..................... 98 6.4.1 More on Regular Expressions.................. 99 6.4.2 Closure......................................103 6.4.3 Some Nice grep Options ......................104 6.4.4 Summary of Regular Expression Characters.....105 6.5 sed: Edit a File to Standard Output.................106 6.6 awk: A Pattern Matching Programming Language........110 6.7 sort: Sort a File...................................114 6.8 What Other Useful UNIX Tools are Available..........117 6.9 Archiver and Library Maintainer.....................118 6.9.1 ar: Creating an Archive File with Object Modules.....................................119 6.9.2 ar: Verifying the Contents of the Archive File.......................................119 6.9.3 ar: Removing Duplicate Object Files..........120 6.9.4 ar: Compiling Main and Archive Files.........120 Workshop 6...............................................121 7. VAX DCL TO UNIX SHELL SCRIPT CONVERSION...................125 7.1 Processes...........................................127 7.2 Pipes...............................................128 7.3 Input, Output, and Error Redirection................129 7.4 Command Structure and File Naming Conventions.......131 7.5 File Management Commands............................133 7.6 Metacharacters......................................135 7.7 Wildcards: Are They Really Wild?....................136 7.8 Summary.............................................137 Workshop 7...............................................139 8. ADVANCED FEATURES OF FTP..................................143 8.1 Initializing FTP on UMAX............................144 8.2 Multiple File Transfers.............................145 8.3 Auto Login Feature..................................146 8.4 Macros..............................................148 8.5 Filename Translation................................149 8.6 Aborting Transfers..................................150 8.7 More Remote Computer Commands.......................151 Workshop 8...............................................153 9. OPTIONAL CHAPTER - KORNSHELL PROGRAMMING..................155 9.1 KornShell Variables.................................155 9.2 User Defined Variables..............................157 9.3 Values of Variables Between Child and Parent Processes...........................................158 9.4 ksh: Aliases........................................159 9.5 ksh: Command Line Editing...........................161 9.6 ksh: Interactive Command Line Editing...............162 9.7 ksh: Functions......................................164 9.8 ksh: The Select Construct...........................166 9.9 ksh: Tracing and Conditional Execution..............168 Workshop 9...............................................169 APPENDIX A - sh...............................................173 APPENDIX B - test.............................................189 APPENDIX C - expr.............................................193 APPENDIX D - ftp..............................................195 APPENDIX E - cc...............................................209 APPENDIX F - f77..............................................219 APPENDIX G - lint.............................................231 APPENDIX H - cb...............................................235 APPENDIX I - ar...............................................237 APPENDIX J - time.............................................243 APPENDIX K - ksh..............................................245 INDEX.........................................................279 I. INTRODUCTION A. Audience This course is for individuals who have completed "UNIX for Beginning Users" (or equivalent experience) and want to write UNIX BourneShell script files. A script file contains a sequence of UNIX commands which can be executed by entering one command. It is assumed that the student already has a good understanding of the UNIX operating system, be able to use a UNIX editor, and be familiar with a computer terminal or typewriter keyboard. B. Course Objectives Upon successful completion of this course the student will be able to: 1. Write moderately complex BourneShell scripts. 2. Make a BourneShell script executable. 3. Demonstrate how to use the following BourneShell commands: shift, exit, expr, test, if then, if then else, if then elif, for, while, until, and case. 4. Use the following BourneShell constructs: tracing mechanisms (for debugging), user variables, BourneShell variables, read-only variables, positional parameters, reading input to a BourneShell script, command substitution, comments, and exporting variables. In addition, test on numeric values, test on file type, and test on character strings are covered. 6. Create a ".profile" script to customize the user environment. 7. Use advanced features of File Transfer Protocol (FTP) 8. Compile source code into object and executable modules. 9. Optional: KornShell programming. This is of primary interest to programmers. 10. Convert VMS DCL command files to UNIX Shell. C. Course Handout Conventions There are several conventions used in this handout for consistency and easier interpretation: 1. Samples of actual terminal sessions are single-lined boxed. 2. User entries are shown in bold print and are underlined. exit 3. All keyboard functions in the text will be bold. (Ret) Backspace Tab Ctrl-F6 Print (Shift-F7) Go to DOS (1) NOTE: (Ret) indicates the Return or Enter key located above the right Shift key. 4. Examples of user entries not showing the computer's response are in dotted-lined boxes. 5. Command formats are double-lined boxed. 6. Three dots either in vertical or horizontal alignment mean continuation or that data is missing from diagram. ????????????????????????????????????????????????????????????????? ? ? ? Multimax, Nanobus, and UMAX are trademarks of ? ? Encore Computer Corporation. ? ? ? ? ? ? Annex is a trademark of XYLOGICS, Inc. ? ? ? ? ? ? UNIX and Teletype are registered trademarks of ? ? AT&T Bell Laboratories ? ? ? ? ? ? Ethernet is a trademark of Xerox Corporation ? ? ? ????????????????????????????????????????????????????????????????? NOTES ????????????????????????????????????????????????????????????????? 1. BOURNESHELL OVERVIEW The BourneShell is both a command-line interpreter and a high- level programming language. When it is acting as a command-line interpreter, it processes commands as you enter them at the command prompt. When you use it as a programming language, it processes commands that are stored in files known as BourneShell scripts. This course will show you how to create and execute BourneShell scripts. We will explore BourneShell programming including such features as variables, control structures, processes, and executable files. The BourneShell is one of three shells available on most UNIX systems. Bourne is the accepted standard for System V UNIX. The other shells are being used more and more. The other shells are the CShell and the KornShell. The CShell is BSD (Berkeley Software Distribution) UNIX. BSD was developed at the University of California at Berkeley, California. Most of the features found in the BourneShell are also found in the other shells; there are differences, however. The CShell and KornShell are not standard on UNIX System V but are generally available. BourneShell scripts allow you to group command lines together and execute them by entering a single command at the command line. This allows complex functions to be completed by any user, and repetitive functions can be completed easily. Input and output can also be redirected from a BourneShell script. 1.1 What is the BourneShell? BourneShell is a high level programming language and a command line interpreter. The command to invoke the BourneShell is: ????????????????????????????????????????????????????????????????? ? Command Format: sh [-acefhiknrstuvx] [args] ? ? ? ? (See Appendix A for a complete list of options etc) ? ????????????????????????????????????????????????????????????????? A Shell script is an executable plain file that contains UNIX and shell commands. To execute the shell script type the name of the script at the prompt. A simple shell script called shell_ex is shown in the following example. The output from the execution of the shell is also shown. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat shell_ex ? ? echo "This is a very simple shell procedure " ? ? echo "created with the basic echo command " ? ? echo "and three other very basic commands " ? ? echo ? ? ps ? ? echo ? ? who ? ? echo ? ? ls ? ? $sh shell_ex ? ? This is a very simple shell procedure ? ? created with the very basic echo command ? ? and three other very basic commands ? ? ? ? PID TTY TIME COMMAND ? ? 10443 rt02120 0:01 sh ? ? 10427 rt02120 0:04 ksh ? ? ? ? sgavlick rt021e0 Sep 7 13:26 ? ? teacher rt021b0 Sep 7 14:39 ? ? ? ? memo ? ? class_notes ? ? $ ? ????????????????????????????????????????????????????????????????? 1.2 Making a Bourne Shell Script Executable A BourneShell script is an ordinary file that contains commands which can be executed in sequence by entering one command at the BourneShell prompt. In order for a script to be executed, it must first be executable. This is done with the chmod command. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat shell_ex ? ? echo "This is a very simple shell procedure " ? ? echo "created with the basic echo command " ? ? echo "and three other very basic commands " ? ? echo ? ? ps ? ? echo ? ? who ? ? echo ? ? ls ? ? $ ? ????????????????????????????????????????????????????????????????? If the ls -l shell_ex command were entered, we would see the protections assigned to this file. Sample Session: ????????????????????????????????????????????????????????????????? ? $ls -l shell_ex ? ? -rw-r--r-- 1 teacher class 66 Sep 7 10:24 shell_ex ? ? $ ? ????????????????????????????????????????????????????????????????? The character in column one is the type of file. - = ordinary (plain) disk file d = directory b = block special file c = character special file p = fifo file ("named pipe") special file l = symbolic link Notice that the script file in the previous sample session has the following file protections: User - Read and Write Group - Read Other - Read No execute permissions have been granted for user, group, or other. If we try to execute this script by typing its name, the following would result. Sample Session: ????????????????????????????????????????????????????????????????? ? $shell_ex ? ? shell_ex: execute permission denied ? ? $ ? ????????????????????????????????????????????????????????????????? This error message would indicate that execute permission was denied. The BourneShell script could not be executed. To change the permissions for the BourneShell script, use the chmod command. Sample Session: ????????????????????????????????????????????????????????????????? ? $chmod 755 shell_ex ? ? $ls -l shell_ex ? ? -rwxr-xr-x 1 teacher class 66 Sep 7 10:26 shell_ex ? ? $ ? ????????????????????????????????????????????????????????????????? Now that the permissions have been changed to allow user, group, and others to execute the file, it will execute properly. Sample Session: ????????????????????????????????????????????????????????????????? ? $shell_ex ? ? This is a very simple shell procedure ? ? created with the basic echo command ? ? and three other very basic commands ? ? ? ? PID TTY TIME COMMAND ? ? 10443 rt02120 0:01 sh ? ? 10427 rt02120 0:04 ksh ? ? ? ? sgavlick rt021e0 Sep 7 13:26 ? . teacher rt021b0 Sep 7 14:39 . . . . . The protections will work as you expect. Execute permission for the user will allow you (the owner) to run the BourneShell script. Group permissions allow anyone in your group to execute the script, and other permission allows anyone on the system to execute the script. 1.3 Tracing Mechanisms It is possible to have a trace made of the BourneShell script as it executes. This is invaluable for debugging purposes. All that is required is to give an option to the BourneShell. This is done by including an option on the call to "sh". The command to do this is: ????????????????????????????????????????????????????????????????? ? Command Format: sh [-acefhiknrstuvx] [args] ? ? ? ? See Appendix A for a complete list of options etc ? ? ? ????????????????????????????????????????????????????????????????? The option to turn on tracing is -x. For an example, let's trace the execution of the simple script shell_ex. Sample session: ????????????????????????????????????????????????????????????????? ? $cat shell_ex ? ? echo "This is a very simple shell procedure " ? ? echo "created with the basic echo command " ? ? echo "and three other very basic commands " ? ? echo ? ? ps ? ? echo ? ? who ? ? echo ? ? ls ? ? $ ? ????????????????????????????????????????????????????????????????? Execute the BourneShell script using the -x option on the call to the shell. The following sample session shows how to do this and it shows the results of the trace. Sample session: ????????????????????????????????????????????????????????????????? ? $sh -x shell_ex ? ? + echo This is a very simple shell procedure ? ? This is a very simple shell procedure ? ? + echo created with the basic echo command ? ? created with the basic echo command ? ? + echo and three other very basic commands ? ? and three other very basic commands ? ? + echo ? ? ? ? + ps ? ? PID TTY TIME COMMAND ? ? 10443 rt01120 0:01 sh ? ? 10427 rt02120 0:04 ksh ? ? + echo ? ? ? ? + who ? ? sgavlick rt021e0 Sep 7 13:26 ? ? teacher rt02120 Sep 7 14:39 ? ? + echo ? ? ? ? + ls ? ? memo ? ? class_notes ? ? $ ? ????????????????????????????????????????????????????????????????? The commands as read from the BourneShell script are indicated by the plus sign (+). The next line or lines are the results of the execution of the command. Using this tracing option allows you to se the execution of each command in the script and see the results of that execution. NOTES ???????????????????????????????????????????????????????????????? Workshop 1 This workshop will reinforce your understanding of the ideas presented in Chapter 1. Each student is to complete the entire workshop. DESK EXERCISES 1. The BourneShell can act as a command line or a high level . 2. The BourneShell is one of three shells generally available. What are the other two? 3. One advantage of using a shell script is . 4. The command to call the BourneShell is: a. bourne b. ksh c. b d. sh 5. Why would you use tracing? 6. What UNIX command do you enter to make a BourneShell script executable? That's all NOTES ????????????????????????????????????????????????????????????????? 2. USER, SHELL, AND READ-ONLY SHELL VARIABLES The BourneShell has no true numeric variables. It uses string variables to represent numbers, as well as text. String variables are able to take on the value of a string of characters. There are three types of variables in the BourneShell. They are user variables, BourneShell variables, and Read-only BourneShell variables. You can declare, initialize, read, and modify user variables from a BourneShell script or from the command line. The BourneShell itself declares and initializes shell variables, but you can read and modify them. The BourneShell also initializes the read-only shell variables, and you can read but not modify them. 2.1 User Variables It is legal to assign any sequence of non-blank characters as the name of a variable. The sample session below creates a variable called person and initializes it with the string Richard. It is important to note that you must NOT precede or follow the equal sign with a space or TAB character. Sample Session: ????????????????????????????????????????????????????????????????? ? $person=Richard ? ????????????????????????????????????????????????????????????????? This sample session indicates that person does not represent the string Richard. The string person is echoed as person. The BourneShell will only do the substitution of the value of the variable when the name of the variable is preceded with a dollar sign ($). Sample Sesssion: ????????????????????????????????????????????????????????????????? ? $echo person ? ? person ? ? $echo $person ? ? Richard ? ? $ ? ????????????????????????????????????????????????????????????????? If you want to have imbedded spaces in a variable, it is necessary to quote the string. Sample Session: ????????????????????????????????????????????????????????????????? ? $person='Richard and Kathleen' ? ? $echo $person ? ? Richard and Kathleen ? ? $ ? ????????????????????????????????????????????????????????????????? The echo utility copies its arguments to the standard output. The command echo $person displays the value of the variable person. It will not display $person because the BourneShell doesn't pass $person as an argument. The leading dollar sign ($) causes the BourneShell to substitute the value of the variable and then passes that value to the utility. The echo utility then displays the value of the variable, not its name, never knowing that you called it with a variable. The BourneShell passed the same command line as if you had typed in echo Richard and Kathleen. The BourneShell can be prevented from doing this substitution by entering one of the following: Sample Sessions: ????????????????????????????????????????????????????????????????? ? $echo $person ? ? Richard and Kathleen ? ? $ ? ????????????????????????????????????????????????????????????????? In this session the contents of the variable person are displayed. The BourneShell made the substitution because the variable name person is preceded by a dollar sign ($). ????????????????????????????????????????????????????????????????? ? $echo \$person ? ? $person ? ? $ ? ????????????????????????????????????????????????????????????????? In the above example the variable person is preceded by a dollar sign ($) but the dollar sign has a backslash (\) ahead of it. The backslash has the effect of cancelling the special meaning of the character following the backslash. In this case, the special meaning of the dollar sign is ignored and the substitution is not done. ????????????????????????????????????????????????????????????????? ? $echo '$person' ? ? $person ? ? $ ? ????????????????????????????????????????????????????????????????? The single quote marks (') causes the characters between the marks to be taken as literal. The shell makes no attempt to interpret the meanings of these characters. The shell passes these characters on with no substitution. ????????????????????????????????????????????????????????????????? ? $echo "$person" ? ? Richard and Kathleen ? ? $ ? ????????????????????????????????????????????????????????????????? The double quote marks do not prevent the shell from making substitution; and the value of the variable will be displayed by the utility. 2.2 Shell Variables The BourneShell declares and initializes variables that determine such things as your home directory, what directories the shell will look in when you give commands, how often to look for mail, your prompt, and many other things. We will look at several of these BourneShell variables and their functions. You can assign new values to these variables from the command line or from the execution of the .profile file in your home directory. 2.2.1 HOME The first BourneShell variable that we will look at is the HOME variable. By default, the home directory is the current working directory after you login. The system administrator determines your home directory when you establish an account and places that information in the /etc/passwd file. When you login, the BourneShell gets that pathname and assigns it to the HOME variable. When you enter a cd command with no argument, the utility takes the name of the directory from the HOME variable and makes it the current working directory. If you change the HOME variable to another directory pathname, the utility will make the new directory the current working directory. Sample Session: ????????????????????????????????????????????????????????????????? ? $echo $HOME ? ? /user0/rharding ? ? $cd ? ? $pwd ? ? /user0/rharding ? ? $HOME=/user0/rharding/eng ? ? $cd ? ? $pwd ? ? /user0/rharding/eng ? ? $ ? ????????????????????????????????????????????????????????????????? This example shows how the value of the HOME variable affects the cd utility. The cd command will use the value of the HOME variable as the pathname for the current working directory. 2.2.2 IFS This is the internal-field separator BourneShell variable. You can always use a space or tab to separate characters on the command line. When you assign the IFS variable to another character, you can also use this character as the field separator. Example: ................................................................. . $num_args a:b:c:d . ................................................................. This example shows only one argument, namely a:b:c:d. ................................................................. . $IFS=: . . $num_args a:b:c:d . ................................................................. This example now shows four different arguments; each being separated by the new IFS, (:). 2.2.3 MAIL The MAIL variable contains the name of the file that the mail (and mailx) utilities use to store your mail. Usually, the absolute pathname of this file is /usr/mail/name, where name is your login name. Example: ................................................................. . $MAIL=/usr/mail/rharding . ................................................................. 2.2.4 MAILPATH This variable contains a list of filenames separated by colons. If set, the BourneShell will inform you when any of these files are modified (i.e. when new mail arrives). Normally, this variable is not set. 2.2.5 MAILCHECK This variable specifies how often, in seconds, the BourneShell will check for new mail. The default is 600 seconds. If set to 0, it will check for new mail each time before it gives you a prompt. 2.2.6 PATH This BourneShell variable will describe the directories that will be searched looking for the program that you want to execute. The BourneShell looks in several directories for a file that has the same name as the command that you entered. The PATH variable controls this search path. Normally, the first directory searched is the current working directory. If the program is not found, the search continues in the /bin and then the /usr/bin directory. Generally, these directories contain executable programs. If the program is not found in one of these directories, the BourneShell reports that the program can't be found (or executed). The PATH variable lists the pathnames in the order in which the search will proceed. The pathnames are separated by a colon (:). If nothing (null string) precedes the colon, that indicates to start the search at the current working directory. Example: ................................................................. . $PATH=:/user0/rharding/bin:/bin:/usr/bin . . $ . ................................................................. This PATH variable indicates to start the search for the program at the current working directory, then look in the directory /user0/rharding/bin, then /bin, and finally /usr/bin. If each user has a unique path specified, each user can execute a different program by giving the same command. The search for the program stops when it is satisfied; thus, you can use the same name for your own programs as the standard UNIX utilities. To do this, simply put your program in one of the first directories that the BourneShell searches. 2.2.7 PS1 This is the BourneShell prompt which lets you know that the shell is waiting for you to give it a command. The default BourneShell prompt is a dollar sign ($). The shell stores the prompt as a string variable in PS1. When you change the value of this variable, the appearance of the prompt will change. When you are working on several different machines, it might be useful to have the prompt be the name of the machine you are working on. Sample Session: ????????????????????????????????????????????????????????????????? ? $pwd ? ? /user0/rharding ? ? $PS1='domax0: ' ? ? domax0: ? ????????????????????????????????????????????????????????????????? Notice that prompt is now domax0: 2.2.8 PS2 This variable is called the secondary prompt. If the command is not completed on one line and must be continued on the next line, the prompt for that continued line is PS2. The default is >. This prompt indicates that the BourneShell is expecting you to finish the previous command line. Sample Session: ????????????????????????????????????????????????????????????????? ? $echo 'demonstration of prompt string ? ? >2' ? ? demonstration of prompt string ? ? 2 ? ? $PS2='Continue? ' ? ? $echo 'demonstration of ? ? Continue? prompt string 2' ? ? demonstration of ? ? prompt string 2 ? ? $ ? ????????????????????????????????????????????????????????????????? Notice how the secondary prompt was changed to "Continue? ". 2.3 Read-Only User Variables The contents of the user variables and the shell variables can be modified by the user. It is possible to assign a new value to them. The new value can be assigned from the dollar ($) prompt or from inside a BourneShell script. Read-only variables are different. The value of read-only variables can not be changed. The variable must be initialized to some value; and then, by entering the following command, it can be made read only. ????????????????????????????????????????????????????????????????? ? Command format: readonly variable_name ? ? ? ? variable_name = name of the variable to be made read only ? ????????????????????????????????????????????????????????????????? Sample Session: ????????????????????????????????????????????????????????????????? ? $person=Kathleen ? ? $readonly person ? ? $echo $person ? ? Kathleen ? ? $person=Richard ? ? person: is read only ? ? $ ? ????????????????????????????????????????????????????????????????? The readonly command given without any arguments will display a list of all the read-only variables. Sample Session: ????????????????????????????????????????????????????????????????? ? $person=Kathleen ? ? $readonly person ? ? $example=Richard ? ? $readonly example ? ? $readonly ? ? readonly person ? ? readonly example ? ? $ ? ????????????????????????????????????????????????????????????????? 2.4 Read-Only Shell Variables The read-only shell variables are similar to the read-only user variables; except the value of these variables is assigned by the shell, and the user CANNOT modify them. 2.4.1 Name of the Calling Program The shell will store the name of the command you used to call a program in the variable named $0. It has the number zero because it appears before the first argument on the command line. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat name_ex ? ? echo 'The name of the command used' ? ? echo 'to execute this script was' $0 ? ? $name_ex ? ? The name of the command used ? ? to execute this script was name_ex ? ? $ ? ????????????????????????????????????????????????????????????????? 2.4.2 Arguments The BourneShell will store the first nine command line arguments in the variables named $1, $2, ..., $9. These variables appear in this section because you cannot change them using the equal sign. It is possible to modify them using the set command. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat arg_ex ? ? echo 'The first five command line' ? ? echo 'arguments are' $1 $2 $3 $4 $5 ? ? $arg_ex Richard Kathleen Douglas ? ? The first five command line ? ? arguments are Richard Kathleen Douglas ? ? $ ? ????????????????????????????????????????????????????????????????? The script arg_ex will display the first five command-line arguments. The variables representing $4 and $5 have a null value. The BourneShell variable $* represents all of the command-line arguments as shown in the following example. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat display_all ? ? echo $* ? ? $display_all Richard Kathleen Douglas ? ? Richard Kathleen Douglas ? ? $ ? ????????????????????????????????????????????????????????????????? The BourneShell variable $# contains the number of arguments on the command line. This is a string variable that represents a decimal number. You can use the expr utility to perform calculations with that number and test to perform logical tests on it. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat num_args ? ? echo 'This script was called with' ? ? echo $# 'arguments' ? ? $num_args Richard Kathleen Douglas ? ? This script was called with ? ? 3 arguments ? ? $ ? ????????????????????????????????????????????????????????????????? 2.4.3 Shift The shift command promotes each of the command-line arguments. The second argument, represented by $2, is now the first argument, represented by $1. The third becomes the second and so on until the last argument becomes the next to last. You can access only the first nine command-line arguments (as $1 through $9). The shift command gives you access to the tenth, and the first becomes unavailable. There is no "unshift" command that will return the arguments that are no longer available. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat demo_shift ? ? echo 'arg1='$1 ' arg2='$2 ' arg3='$3 ? ? shift ? ? echo 'arg1='$1 ' arg2='$2 ' arg3='$3 ? ? shift ? ? echo 'arg1='$1 ' arg2='$2 ' arg3='$3 ? ? shift ? ? echo 'arg1='$1 ' arg2='$2 ' arg3='$3 ? ? shift ? ? $demo_shift Richard Kathleen Douglas ? ? arg1=Richard arg2=Kathleen arg3=Douglas ? ? arg1=Kathleen arg2=Douglas arg3= ? ? arg1=Douglas arg2= arg3= ? ? demo_shift: cannot shift ? ? $ ? ????????????????????????????????????????????????????????????????? The BourneShell will display an error message when the script executes a shift command after it has run out of variables. 2.4.4 Set The Set command will display a list of all the variables that are set when it has no arguments. Sample Session: ????????????????????????????????????????????????????????????????? ? $set ? ? HOME=/user0/teacher ? ? IFS= ? ? ? ? LOGNAME=richard ? ? MAIL=/usr/mail/richard ? ? MAILCHECK=600 ? ? PATH=:/bin:/usr/bin ? ? PS1=$ ? ? PS2=> ? ? SHELL=/bin/sh ? ? TERM=vt100 ? ? TZ=MST7MDT ? ? $ ? ????????????????????????????????????????????????????????????????? When set is called with arguments, it sets the value of the command-line arguments ($1-$n) to the arguments. The example sets the first three arguments. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat set_ex ? ? set who really cares ? ? echo $#: $* ? ? $set_ex ? ? 3: who really cares ? ? $ ? ????????????????????????????????????????????????????????????????? 2.4.5 expr The expr command will perform arithmetic in the BourneShell. ????????????????????????????????????????????????????????????????? ? Command format: expr expression ? ? ? ? See Appendix C for a complete list of expressions ? ????????????????????????????????????????????????????????????????? The arguments are taken as an expression. After the evaluation has taken place, the result is written to standard output. The terms of the expression must be separated by blanks. Special characters to the shell must be escaped. Strings containing blanks or other special characters must be quoted. Sample Session: ????????????????????????????????????????????????????????????????? ? $expr 7 + 8 + 10 ? ? 25 ? ? $expr 10 - 8 ? ? 2 ? ? $expr 10 '*' 4 ? ? 40 ? ? $expr 135 / 5 ? ? 27 ? ? $ ? ????????????????????????????????????????????????????????????????? expr will also work with user defined variables as in the following example: Sample Session: ????????????????????????????????????????????????????????????????? ? $cat data ? ? 8 ? ? 15 ? ? 25 ? ? $cat express ? ? count=0 ? ? tot=0 ? ? for a in `cat data` ? ? do ? ? tot=`expr $tot + $a` ? ? count=`expr $count + 1` ? ? done ? ? avg=`expr $tot / $count` ? ? echo "The average is $avg" ? ? $ ? ????????????????????????????????????????????????????????????????? Let's execute the script "express" with tracing on so we can follow the execution. Sample Session: ????????????????????????????????????????????????????????????????? ? $sh -x express ? ? count=0 ? ? tot=0 ? ? + cat data ? ? + expr 0 + 8 ? ? tot=8 ? ? + expr 0 + 1 ? ? count=1 ? ? + expr 8 + 15 ? ? tot=23 ? ? + expr 1 + 1 ? ? count=2 ? ? + expr 23 + 25 ? ? tot=48 ? ? + expr 2 + 1 ? ? count=3 ? ? + expr 48 / 3 ? ? avg=16 ? ? + echo The average is 16 ? ? The average is 16 ? ? $ ? ????????????????????????????????????????????????????????????????? NOTES ????????????????????????????????????????????????????????????????? NOTES ????????????????????????????????????????????????????????????????? Workshop 2 This workshop will reinforce your understanding of the ideas presented in Chapter 2. Login to the Multimax using the username and password given to you by the instructor. Each student is to complete the entire workshop. DESK EXERCISES 1. Any series of non-blank characters can be assigned to a user variable. True/False 2. How can you insert a space into a user variable? 3. What utility can be used to display the contents of a user variable to standard output? 4. The backslash (\) character is used to remove the special meaning of some characters. True/False 5. What other character can be used to prevent the shell from doing the substitution? 6. Double quote marks will prevent the shell from making the substitution. True/False Continue on the next page 7. What do the following shell variables do? HOME IFS MAIL MAILPATH MAILCHECK PATH PS1 PS2 Continue on the next page 8. What is the command to create a read-only user variable? 9. What is the read-only shell variable that represents the calling program? 10. What do $1,$2,...,$9 represent? 11. What BourneShell variable represents all of the command line arguments? 12. What does the shift command do? 13. What is displayed when you enter set with no arguments? Continue on the next page COMPUTER EXERCISES 14. Login to the Multimax (domax1) using the username and password given to you by the instructor. 15. Create a subdirectory called sub_dir. 16. Modify your .profile to include the following: a) Change the home directory to sub_dir b) Set the internal-field separator to a comma c) Have mail messages saved into mail1. d) Set the PATH to look for programs in the following directories: $HOME/bin /bin /usr/bin e) Change the prompt to reflect the name of the system f) Change the secondary prompt to 'More?' 17. Execute the .profile Enter $. .profile 18. Verify that the changes are correct. If you have extra time go to the next page. Extra Mile on the next page Extra Mile Change the .profile file so the date/time and a list of all users that are currently logged in will be displayed on your monitor screen automatically when you login. NOTES ????????????????????????????????????????????????????????????????? 3. POSITIONAL PARAMETERS A BourneShell script can also read in command-line arguments. The first argument is referred to as $1, the second is $2, and so on. Command-line arguments are referred to as positional parameters. Let's look at an example BourneShell script to see how these are used. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat neat_shell ? ? echo $1 $2 $3 ? ? echo $0 is the name of the shell script ? ? echo "There were $# arguments." ? ? echo $* ? ? $ ? ????????????????????????????????????????????????????????????????? Insure that the BourneShell script is executable by issuing this command: Sample Session: ????????????????????????????????????????????????????????????????? ? $chmod a+x neat_shell ? ? $ ? ????????????????????????????????????????????????????????????????? Now, if we type the name of the BourneShell script with no arguments, we get the following results. Sample Session: ????????????????????????????????????????????????????????????????? ? $neat_shell ? ? ? ? neat_shell is the name of the shell script ? ? There were 0 arguments. ? ? ? ? $ ? ????????????????????????????????????????????????????????????????? In this sample session, there were no arguments given so none were printed. $0 is the positional parameter that refers to the name of the script. Since there were no arguments given with this invocation of neat_shell, there were zero arguments listed. 3.1 Reading Input Into a Shell Variable The BourneShell script can read user input from standard input. The read command will read one line from standard input and assign the line to one or more variables. The following example shows how this works. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat read_script ? ? echo "Please enter a string of your choice" ? ? read a ? ? echo $a ? ? $ ? ????????????????????????????????????????????????????????????????? This simple script will read one line from standard input (keyboard) and assign it to the variable a. Sample Session: ????????????????????????????????????????????????????????????????? ? $read_script ? ? Please enter a string of your choice ? ? Here it is ? ? Here it is ? ? $ ? ????????????????????????????????????????????????????????????????? The line read from standard input can also be assigned to several variables as shown in the following example. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat reads ? ? echo "Please enter three strings" ? ? read a b c ? ? echo $a $b $c ? ? echo $c ? ? echo $b ? ? echo $a ? ? $ ? ????????????????????????????????????????????????????????????????? This time, we will turn on the trace mechanism and follow the execution of this BourneShell script. Sample Session: ????????????????????????????????????????????????????????????????? ? $sh -x reads ? ? + echo Please enter three strings ? ? Please enter three strings ? ? + read a b c ? ? this is more than three strings ? ? + echo this is more than three strings ? ? this is more than three strings ? ? + echo more than three strings ? ? more than three strings ? ? + echo is ? ? is ? ? + echo this ? ? this ? ? $ ? ????????????????????????????????????????????????????????????????? It is interesting to note that the spaces separate the values for the variables a,b, and c. For example, the variable a was assigned the string this, the variable b was assigned the string is, and the remainder of the line was assigned to c (including the spaces). Sample Session: ????????????????????????????????????????????????????????????????? ? $cat read_ex ? ? echo 'Enter line: \c' ? ? read line ? ? echo "The line was: $line" ? ? $ ? ????????????????????????????????????????????????????????????????? In this example, the \c option will suppress the carriage return. The single quote marks protect the backslash from being interpreted by the shell. Also notice that the double quote marks have no effect on the substitution of the variable line. Sample Session: ????????????????????????????????????????????????????????????????? ? $read_ex ? ? Enter line: All's well that ends well ? ? The line was: All's well that ends well ? ? $ ? ????????????????????????????????????????????????????????????????? 3.2 Command Substitution You can execute a command by enclosing it within two grave accent marks [these are sometimes called backquotes (`)]. The BourneShell will replace the command and the grave marks with the output from the command. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat dir ? ? dir=`pwd` ? ? echo 'You are using the' $dir 'directory' ? ? $ ? ????????????????????????????????????????????????????????????????? NOTE: The grave marks lean to the left, and the apostrophes lean to the right. The grave marks enclose the pwd command. Sample Session: ????????????????????????????????????????????????????????????????? ? $dir ? ? You are using the /user0/rharding directory ? ? $ ? ????????????????????????????????????????????????????????????????? The important thing to notice here is that the pwd command was executed; and the output, /user0/rharding, was then assigned to the variable dir. It is not necessary to assign the output of a command to a variable as shown in the previous example. The command substitution can occur directly as shown in the next example. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat dir2 ? ? echo 'You are using the' `pwd` 'directory' ? ? $dir2 ? ? You are using the /user0/rharding directory ? ? $ ? ????????????????????????????????????????????????????????????????? One final example will show a practical use of command substitution. This BourneShell script will use the date command to provide the date in a useful format. The normal output from the date command looks like the following. Sample Session: ????????????????????????????????????????????????????????????????? ? $date ? ? Wed Sep 12 18:02:05 MDT 1990 ? ? $ ? ????????????????????????????????????????????????????????????????? Here's a BourneShell script that rearranges the output into a more useable format. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat dateset ? ? set `date` ? ? echo $* ? ? echo ? ? echo 'Argument 1:' $1 ? ? echo 'Argument 2:' $2 ? ? echo 'Argument 3:' $3 ? ? echo 'Argument 4:' $4 ? ? echo ? ? echo $2 $3, $6 ? ? $dateset ? ? Wed Sep 12 18:02:05 MDT 1990 ? ? ? ? Argument 1: Wed ? ? Argument 2: Sep ? ? Argument 3: 12 ? ? Argument 4: 18:02:05 ? ? ? ? Sep 12, 1990 ? ? $ ? ????????????????????????????????????????????????????????????????? The first command in the BourneShell script dateset uses the grave accent marks to set the command-line argument variables to the output of the date command. The next commands show the first four of these argument variables. The final command displays the arguments in a different order that could be useful in a report or a letter. 3.3 Comments in BourneShell Scripts Comments can be inserted into the BourneShell script by beginning each comment line with the pound symbol (#) or a colon (:). All characters after the comment character will be ignored by the shell. The only exception to this rule is that the first character of the first line must not be a pound symbol; if the first character is a pound sign, the BourneShell tries to execute the script as if it was written in CShell syntax. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat com_sub ? ? # The first line sets your present working directory ? ? # to the variable 'directory' ? ? directory=`pwd` ? ? # The second line sets the date to the variable 'when' ? ? when=`date` ? ? : The third line will echo on the screen ? ? echo "You are in $directory on $when" ? ? : You could have said echo : ? ? : "You are in `pwd` on `date`" ? ? : to have a one line program ? ? $ ? ????????????????????????????????????????????????????????????????? 3.4 BourneShell Environment - Exporting Variables Within a process, you can declare, initialize, read, and modify variables. The variable is local to that process. When a process forks a child process, the parent process does not automatically pass the value of the variable to the child process. Here is an example of the variables not being exported. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat no_export ? ? car=mercedes # set the variable ? ? echo $0 $car $ # $0 = name of file executed ? ? # $car =value of variable car ? ? # $ = PID number (process id) ? ? inner # execute another BourneShell script ? ? echo $0 $car $ # display same as above ? ? $cat inner ? ? echo $0 $car $ # display variables for this process ? ? $chmod a+x no_export ? ? $chmod a+x inner ? ? $no_export ? ? no_export mercedes 4790 ? ? inner 4792 ? ? no_export mercedes 4790 ? ? $ ? ????????????????????????????????????????????????????????????????? When no_export was executed, it, of course, assigned a value of mercedes to the variable car and printed it out. The call to inner created a child process. Its PID is 4792, while the parent PID is 4790. Notice, when inner tried to print the value of car, it printed nothing. The reason is because the value of car was not passed by the parent. Can the value be passed from parent to child process? Yes, by using the export command. Let's look at an example. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat export_it ? ? car=mercedes ? ? export car ? ? echo $0 $car $ ? ? inner1 ? ? echo $0 $car $ ? ? $cat inner1 ? ? echo $0 $car $ ? ? car=chevy ? ? echo $0 $car $ ? ? $chmod a+x export_it ? ? $chmod a+x inner1 ? ? $export_it ? ? export_it mercedes 4798 ? ? inner1 mercedes 4800 ? ? inner1 chevy 4800 ? ? export_it mercedes 4798 ? ? $ ? ????????????????????????????????????????????????????????????????? In the export_it BourneShell script, the variable car was initialized to mercedes; and then it was exported. This means that the value of car is now available to a child process. When inner1 prints out the value of car it has the value of mercedes. This is as we expect because the value of car was exported from the parent. The next line of inner1 changes the value of car to chevy. This is shown in the next line of the sample session. The last line of the session shows the return to the parent process and the value is still mercedes. How is this possible? Exporting variables is only valid from the parent to the child process. The child process cannot change the parent's variable. Workshop 3 This workshop will reinforce your understanding of the ideas presented in Chapter 3. Login to the Multimax using the username and password given to you by the instructor. Each student is to complete the entire workshop. DESK EXERCISES 1. What is the positional parameter that represents the name of the command? 2. What positional parameter stands for the number of arguments on the command line? 3. What command will read one line from standard input and assign the value to a variable? 4. What character is used to indicate command substitution? 5. What are the two characters that indicate comments in BourneShell scripts? Continue on the next page 6. Why is it bad practice to put a pound sign (#) in the first character position of the first line of a BourneShell script? 7. Variables set by the parent process are automatically known to the child process. True/False 8. What command will allow the value of a variable to be passed to a child process? 9. Can a child process change the value of the parents' variable? Why? COMPUTER EXERCISES 10. Write a BourneShell script called "reverse_it" that has three strings as parameters and then display the strings in opposite order. Be sure to include appropriate comments. Hint: positional parameters 11. Write a BourneShell script called "read_it" that does the same as question 10 but prompts the user to enter each string separately. How would you trace the execution of this script. Do it! Continue on the next page. 12. Write a BourneShell script that uses the output of the "date" command and changes it from: Wed Sep 12 18:02:05 MDT 1990 to: Sep 12, 1990 18:02:05 NOTES ????????????????????????????????????????????????????????????????? 4. CONTROL CONSTRUCTS: The BourneShell control constructs can alter the flow of control within the script. The BourneShell provides simple two-way branch if statements and multiple-branch case statements, plus for, while, and until statements. In discussing these control structures, the BourneShell keywords will be in bold type and the normal type are the user supplied items to cause the desired effect in command format boxes. 4.1 Types of Tests Used with Control Constructs: The test utility evaluates expressions and returns a condition indicating whether or not the expression is true (equal to zero) or false (not equal to zero). There are no options with this utility. The format for this utility is as follows: ????????????????????????????????????????????????????????????????? ? Command Format: test expression ? ? ? ? expression - composed of constants, variables, and ? ? operators ? ????????????????????????????????????????????????????????????????? Expressions will be looked at in greater detail later with some examples. There are a few items that need to be mentioned that apply to expressions. Expressions can contain one or more evaluation criteria that test will evaluate. A -a that separates two criteria is a logical AND operator. In this case, both criteria must evaluate to true in order for test to return a value of true. The -o is the logical OR operator. When this operator separates two criteria, one or the other (or both) must be true for test to return a true condition. You can negate any criterion by preceding it with an exclamation mark (!). Parentheses can be used to group criteria. If there are no parentheses, the -a (logical AND operator) takes precedence over the -o (logical OR operator). The test utility will evaluate operators of equal precedence from left to right. Within the expression itself, you must put special characters, such as parentheses, in quote marks so the BourneShell will not evaluate them but will pass them to test. Since each element (evaluation criterion, string, or variable) in an expression is a separate argument, each must be separated by a space. The test utility will work from the command line but it is more often used in a script to test input or verify access to a file. Another way to do the test evaluation is to surround the expression with left and right brackets. A space character must appear after the left bracket and before the right bracket. test expression = [ expression ] 4.2 Test on Numeric Values Test expressions can be in many different forms. The expressions can appear as a set of evaluation criteria. The general form for testing numeric values is: ????????????????????????????????????????????????????????????????? ? int1 op int2 ? ????????????????????????????????????????????????????????????????? This criterion is true if the integer int1 has the specified algebraic relationship to integer int2. The valid operators (op) are: -eq equal -ne not equal -gt greater than -lt less than -ge greater than or equal -le less than or equal 4.3 Test on Character Strings The evaluation criterion for character strings is similar to numeric comparisons. The general form is: string1 op string2 The operators (op) are: string1 = string2 true if string1 and string 2 are equal string1 != string2 true if string1 and string2 are not equal string1 true if string1 is not the null string Sample Session: ????????????????????????????????????????????????????????????????? ? $ cat test_string ? ? number=1 ? ? numero=0001 ? ? if test $number = $numero ? ? then echo "String vals for $number and $numero are =" ? ? else echo "String vals for $number and $numero not =" ? ? fi ? ? if test $number -eq $numero ? ? then echo "Numeric vals for $number and $numero are =" ? ? else echo "Numeric vals for $number and $numero not =" ? ? fi ? ? $chmod 755 test_string ? ? $sh -x test_string ? ? number=1 ? ? numero=0001 ? ? + test 1 = 0001 ? ? + echo String vals for 1 and 0001 not = ? ? String vals for 1 and 0001 not = ? ? + test 1 -eq 0001 ? ? + echo Numeric vals for 1 and 0001 are = ? ? Numeric vals for 1 and 0001 are = ? ? $test_string ? ? String vals for 1 and 0001 not = ? ? Numeric vals for 1 and 0001 are = ? ? $ ? ????????????????????????????????????????????????????????????????? 4.4 Test on File Types The test utility can be used to determine information about file types. All of the criterion can be found in Appendix B. A few of them are listed here: -r filename true if filename exists and is readable -w filename true if filename exists and is writable -x filename true if filename exists and is executable -f filename true if filename exists and it is a plain file -d filename true if filename exists and it is a directory. -s filename true if filename exits and it contains information (has a size greater than 0 bytes) Example: ................................................................. . $test -d new_dir . ................................................................. If new_dir is a directory, this criterion will evaluate to true. If it does not exist, then it will be false. 4.5 if then The format for this construct is: ????????????????????????????????????????????????????????????????? ? Command Format: if expression ? ? then commands ? ? fi ? ????????????????????????????????????????????????????????????????? The if statement evaluates the expression and then returns control based on this status. The fi statement marks the end of the if, notice that fi is if spelled backward. The if statement executes the statements immediately following it if the expression returns a true status. If the return status is false, control will transfer to the statement following the fi. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat check_args ? ? if (test $# = 0) ? ? then echo 'Please supply at least 1 argument' ? ? exit ? ? fi ? ? echo 'Program is running' ? ? $ ? ????????????????????????????????????????????????????????????????? This little script will check to insure that you are giving at least one argument. If none are given it will display the error message and exit. If one or more arguments are given it will display "Program is running" and run the rest of the script, if any. Sample Session: ????????????????????????????????????????????????????????????????? ? $check_args ? ? Please supply at least 1 argument ? ? $check_args xyz ? ? Program is running ? ? $ ? ????????????????????????????????????????????????????????????????? 4.6 if then else The format for this construct is: ????????????????????????????????????????????????????????????????? ? Command Format: if expression ? ? then commands ? ? else commands ? ? fi ? ????????????????????????????????????????????????????????????????? The else part of this structure makes the single-branch if statement into a two-way branch. If the expression returns a true status, the commands between the then and the else statement will be executed. After these have been executed, control will start again at the statement after the fi. If the expression returns false, the commands following the else statement will be executed. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat test_string ? ? number=1 ? ? numero=0001 ? ? if test $number = $numero ? ? then echo "String values of $number and $numero are equal" ? ? else echo "String values of $number and $numero not equal" ? ? fi ? ? if test $number -eq $numero ? ? then echo "Numeric values of $number and $numero are equal" ? ? else echo "Numeric values of $number and $numero not equal" ? ? fi ? ????????????????????????????????????????????????????????????????? Let's follow the execution of this script with tracing. Sample Session: ????????????????????????????????????????????????????????????????? ? $sh -x test_string ? ? number=1 ? ? numero=0001 ? ? + test 1 = 0001 ? ? + echo String values of 1 and 0001 are not equal ? ? String values of 1 and 0001 are not equal ? ? + test 1 -eq 0001 ? ? + echo Numeric values of 1 and 0001 are equal ? ? Numeric values of 1 and 0001 are equal ? ? $chmod a+x test_string ? ? $test_string ? ? String values of 1 and 0001 are not equal ? ? Numeric values of 1 and 0001 are equal ? ? $ ? ????????????????????????????????????????????????????????????????? 4.7 if then elif The format for this construct is: ????????????????????????????????????????????????????????????????? ? Command Format: if expression ? ? then commands ? ? elif expression ? ? then commands ? ? else commands ? ? fi ? ????????????????????????????????????????????????????????????????? The elif construct combines the else and if statements and allows you to construct a nested set of if then else structures. 4.8 for The format for this construct is: ????????????????????????????????????????????????????????????????? ? Command Format: for loop-index in argument-list ? ? do ? ? commands ? ? done ? ????????????????????????????????????????????????????????????????? This structure will assign the value of the first item in the argument list to the loop index and executes the commands between the do and done statements. The do and done statements indicate the beginning and end of the for loop. After the structure passes control to the done statement, it assigns the value of the second item in the argument list to the loop index and repeats the commands. The structure will repeat the commands between the do and done statements once for each argument in the argument list. When the argument list has been exhausted, control passes to the statement following the done. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat find_henry1 ? ? for x in project1 project2 project3 ? ? do ? ? grep henry $x ? ? done ? ????????????????????????????????????????????????????????????????? Sample Session: ????????????????????????????????????????????????????????????????? ? $head project? ? ? ==> project1 <== ? ? henry ? ? joe ? ? mike ? ? sue ? ? ? ? ==> project2 <== ? ? joe ? ? mike ? ? sue ? ? ? ? ==> project3 <== ? ? joe ? ? mike ? ? sue ? ? henry ? ? ? ? ==> project4 <== ? ? joe ? ? mike ? ? ? ? $find_henry ? ? henry ? ? henry ? ? $ ? ????????????????????????????????????????????????????????????????? Each file in the argument list was searched for the string, henry. When a match was found, the string was printed. 4.9 while The format for this construct is: ????????????????????????????????????????????????????????????????? ? Command Format: while expression ? ? do ? ? commands ? ? done ? ????????????????????????????????????????????????????????????????? As long as the expression returns a true exit status, the structure continues to execute the commands between the do and the done statement. Before each loop through the commands, the structure executes the expression. When the exit status of the expression is false (non-zero), control is passed to the statement following the done statement. The commands to be executed must change the expression test or an infinite loop can result. 4.10 until The format for this construct is: ????????????????????????????????????????????????????????????????? ? Command Format: until expression ? ? do ? ? commands ? ? done ? ????????????????????????????????????????????????????????????????? The until and while structures are very similar. The only difference is that the test is at the top of the loop. The until structure will continue to loop until the expression returns true or a nonerror condition. The while loop will continue as long as a true or nonerror condition is returned. The commands to be executed must change the expression test or an infinite loop can result. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat until_ex ? ? secretname='jenny' ? ? name='noname' ? ? echo 'Try to guess the secret name!' ? ? echo ? ? until (test "$name" = "$secretname") ? ? do ? ? echo 'Your guess: \c' ? ? read name ? ? done ? ? echo 'You did it!' ? ? $ ? ????????????????????????????????????????????????????????????????? The until loop will continue until name is equal to the secret name. Sample Session: ????????????????????????????????????????????????????????????????? ? $chmod a+x until_ex ? ? $until_ex ? ? Try to guess the secret name! ? ? ? ? Your guess: gaylan ? ? Your guess: art ? ? Your guess: richard ? ? Your guess: jenny ? ? You did it! ? ? $ ? ????????????????????????????????????????????????????????????????? 4.11 case The format for this construct is: ????????????????????????????????????????????????????????????????? ? Command Format: case test-string in ? ? pattern-1 ) commands-1 ;; ? ? pattern-2 ) commands-2 ;; ? ? pattern-3 ) commands-3 ;; ? ? . ? ? . ? ? . ? ? *) commands ;; ? ? esac ? ????????????????????????????????????????????????????????????????? The case structure allows a multiple-branch decision mechanism. The path that is taken depends on a match between the test-string and one of the patterns. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat case_ex ? ? echo 'Enter A, B, or C: \c' ? ? read letter ? ? case $letter in ? ? A) echo 'You entered A' ;; ? ? B) echo 'You entered B' ;; ? ? C) echo 'You entered C' ;; ? ? *) echo 'You did not enter A, B, or C' ;; ? ? esac ? ? $chmod a+x case_ex ? ? $case_ex ? ? Enter A, B, or C: B ? ? You entered B ? ? $case_ex ? ? Enter A, B, or C: b ? ? You did not enter A, B, or C ? ? $ ? ????????????????????????????????????????????????????????????????? This example uses the value of a character that the user entered as the test string. The value is represented by the variable letter. If letter has the value of A, the structure will execute the command following A. If letter has a value of B or C, then the appropriate commands will be executed. The asterisk indicates any string of characters; and it, therefore, functions as a catchall for a no-match condition. The lowercase b in the second sample session is an example of a no match condition. NOTES ????????????????????????????????????????????????????????????????? NOTES ????????????????????????????????????????????????????????????????? Workshop 4 This workshop will reinforce your understanding of the ideas presented in Chapter 4. Login to the Multimax using the username and password given to you by the instructor. Each student is to complete the entire workshop. DESK EXERCISES 1. Which utility will evaluate an expression and then return a condition indicating whether or not the expression is true (equal to zero) or false (not equal to zero)? 2. What are the operators for character string comparisons? Continue on the next page COMPUTER EXERCISES 3. Use the "if then" construct to write a BourneShell script that will check for at least two parameters being present on the command line. Output an appropriate error message. 4. Write a BourneShell script using the "if then else" construct that will check for equality of two strings that are supplied as parameters to the script. Output a message stating if the strings are equal or not equal. 5. Write a BourneShell script using the "if then elif" construct that will check two numbers, input as parameters, and tell if the first parameter is greater than, equal to, or less than the second number. Output appropriate error messages. 6. Write a BourneShell script using the "for" construct that has a loop index called "fruit" and an argument list as follows: apples oranges bananas pears. Echo the name of each argument to the monitor screen and when the last argument is listed output an appropriate message. Continue on the next page 7. Write a BourneShell script using the "while" construct that will add all the numbers between 0 and 9 and display the result. The sum of the digits 0 through 9 is 45. 8. Write a BourneShell script using the "until" construct similar to the example in the manual except compare numbers instead of strings. 9. Write a BourneShell script using the "case" statement that will ask you to enter the day of the week and then echo that day to the monitor screen. Be sure to include an appropriate message if you enter in a string other than a valid day of the week. EXTRA MILE 10. Write a BourneShell script called "dir_num" that will test all of the files in the current directory and print all the files that prove to be a directory. NOTES ????????????????????????????????????????????????????????????????? 5. COMPILING PROGRAMS IN UNIX This chapter will examine compiling source code programs in three high level languages "C", FORTRAN, and COBOL. The second part of the chapter will look at the archive and library maintainer. The archive allows you to create a library of object modules. These files are used by the link editor. 5.1 "C": Sample Program with a Main and Two Functions in One File Based on the command line options, cc compiles, assembles, and load C language source code programs. It can also assemble and load assembly language source programs or merely load object programs. ????????????????????????????????????????????????????????????????? ? Command Format: cc [options] file-list ? ? ? ? (See Appendix E for a complete list of options) ? ????????????????????????????????????????????????????????????????? When using the cc utility, the following conventions are observed: 1. A filename with the extension of .c indicates a C language source program. 2. A filename with an extension of .s indicates an assembly language source program. 3. A filename with an extension of .o indicates an object program. The cc utility will take its input from the file or files you specify on the command line. Unless you use the -o option, it will store the executable program in a file called a.out. Sample C Language Source Code Program: ????????????????????????????????????????????????????????????????? ? $cat hello.c ? ? main () ? ? { ? ? printf ("Hello from main!\n\n"); ? ? printf ("Calling function1!\n\n"); ? ? funct1(); ? ? printf ("\t Back from function1!\n\n"); ? ? printf ("Calling function2!\n\n"); ? ? funct2(); ? ? printf ("\t Back from funct2!\n\n"); ? ? printf ("That's all!\n\n"); ? ? } ? ? funct1() ? ? { ? ? printf ("\t\t Hello from function1!\n\n); ? ? } ? ? funct2() ? ? { ? ? printf ("\t\t Hello from function2!\n\n); ? ? } ? ????????????????????????????????????????????????????????????????? 5.2 "C": Compiling a Program To compile the previous example program into an executable module, enter the following command at the command line. Sample Session: ????????????????????????????????????????????????????????????????? ? $cc hello.c ? ? $ ? ????????????????????????????????????????????????????????????????? Without any options, cc accepts C source code and assembly language programs that follow the conventions outlined above. It will compile, assemble, and load these programs to produce an executable called a.out. The cc utility puts the object code in files with the same base filename (everything before the period) as the source but with a filename extension of .o . The a.out stands for assembly output. This is the default. Sample Session: ????????????????????????????????????????????????????????????????? ? $cc hello.c ? ? $a.out ? ? Hello from main! ? ? ? ? Calling function1! ? ? ? ? Hello from function1! ? ? ? ? Back from function1! ? ? ? ? Calling function2! ? ? ? ? Hello from function2! ? ? ? ? Back from function2! ? ? ? ? That's all! ? ? $ ? ????????????????????????????????????????????????????????????????? NOTE: The a.out file that was created by the cc utility has the following permissions: user - read, write, and execute group - read and execute other - read and execute It is not necessary for you to change the permissions using the chmod command because the cc utility set the execute permissions for you. 5.3 "C": Renaming the Executable Module You can rename the executable module using the mv command. The file permissions will be the same as before the file is renamed. Sample Session: ????????????????????????????????????????????????????????????????? ? $mv a.out hello ? ? $hello ? ? Hello from main! ? ? ? ? Calling function1! ? ? ? ? Hello from function1! ? ? ? ? Back from function1! ? ? ? ? Calling function2! ? ? ? ? Hello from function2! ? ? ? ? Back from function2! ? ? ? ? That's all! ? ? $ ? ????????????????????????????????????????????????????????????????? 5.4 "C": Giving a Name to the Output File It is possible to have the output sent to a file you specify instead of a.out by using the following command: ????????????????????????????????????????????????????????????????? ? Command Format: cc -o output source ? ? ? ? output - the name of the executable file ? ? ? ? source - the name of the C source code file ? ????????????????????????????????????????????????????????????????? The -o option tells cc to tell the link editor to use the specified name for the output instead of the default a.out. NOTE: It is not necessary for the -o option to appear after the cc command. The filename that appears after the -o is the name of the output file. For example, cc source - o output is the same as cc -o output source. Sample Session: ????????????????????????????????????????????????????????????????? ? $cc -o hello hello.c ? ? $hello ? ? Hello from main! ? ? Calling function1! ? ? ? ? Hello from function1! ? ? ? ? Back from function1! ? ? ? ? Calling function2! ? ? ? ? Hello from function2! ? ? ? ? Back from function2! ? ? ? ? That's all! ? ? $ ? ????????????????????????????????????????????????????????????????? 5.5 "C": Producing an Assembly Listing This option causes cc to compile C programs and leave the corresponding assembly language source programs in a file with filename extensions of .s. ????????????????????????????????????????????????????????????????? ? Command Format: cc -S hello.c ? ? ? ? -S = Compile only ? ????????????????????????????????????????????????????????????????? Sample Session: ????????????????????????????????????????????????????????????????? ? $cc -S hello.c ? ? $ls -C ? ? example.f hello hex.c octal.c ? ? hello.c hello.s multiply.c ? ? $ ? ????????????????????????????????????????????????????????????????? 5.6 "C": Main and Two Functions in Three Separate Source Files This is the same C program that we have seen before, except it is now in three files rather than one as before. The three files are main.c, funct1.c, and funct2.c. ????????????????????????????????????????????????????????????????? ? $cat main.c ? ? main () ? ? { ? ? printf ("Hello from main!\n\n"); ? ? printf ("Calling function1!\n\n"); ? ? funct1(); ? ? printf ("\t Back from function1!\n\n"); ? ? printf ("Calling function2!\n\n"); ? ? funct2(); ? ? printf ("\t Back from funct2!\n\n"); ? ? printf ("That's all!\n\n"); ? ? } ? ? $cat funct1.c ? ? funct1() ? ? { ? ? printf ("\t\t Hello from function1!\n\n); ? ? } ? ? $cat funct2.c ? ? funct2() ? ? { ? ? printf ("\t\t Hello from function2!\n\n); ? ? } ? ????????????????????????????????????????????????????????????????? 5.7 "C": Compiling but Not Producing an Executable Module Using the previous program, the following command will compile but not produce an executable module. ????????????????????????????????????????????????????????????????? ? Command Format: cc -c main.c funct1.c funct2.c ? ? ? ? -c = Compile, but do not load object files. This option ? ? causes cc to compile and/or assemble source code ? ? programs and leave the corresponding object programs ? ? in files with filename extensions of .o. ? ????????????????????????????????????????????????????????????????? Sample Session: ????????????????????????????????????????????????????????????????? ? $cc -c main.c funct1.c funct2.c ? ? main.c: ? ? funct1.c: ? ? funct2.c: ? ? $ls a.out ? ? a.out not found ? ? $ls -C *.o ? ? funct1.o funct2.o main.o ? ? $ ? ????????????????????????????????????????????????????????????????? The -c options causes the compilation system to suppress the link edit phase. This produces an object file or files, in this example (main.o funct1.o funct2.o), that can be link edited at a later time with the cc command with no options. 5.8 FORTRAN: Sample Program a Main and Two Subroutines There are several conventions for use with the FORTRAN compiler. They are: 1. The name of the file containing the FORTRAN source code must end with .f. 2. The compiler is invoked with f77. 3. Several options are available with the compiler. (-c, -o, -p, -S) 4. Preconnections are made for stdin (unit5) and stdout (unit6). This is the FORTRAN source code example to be used in the following discussions of the FORTRAN compiler. Sample Session: ????????????????????????????????????????????????????????????????? ? $cat hello.f ? ? program calling ? ? write(6,100) ? ? 100 format (' Hello from main!',/) ? ? write(6,110) ? ? 110 format(' Calling subroutine1!',/) ? ? call sub1 ? ? write(6,120) ? ? 120 format(t15' Back from subroutine1!',/) ? ? write(6,130) ? ? 130 format(' Calling subroutine2!',/) ? ? call sub2 ? ? write(6,140) ? ? 140 format(t15' Back from subroutine2!',/) ? ? write(6,150) ? ? 150 format(' That's all, folks!') ? ? end ? ? subroutine sub1 ? ? write(6,200) ? ? 200 format(t20,' Hello from subroutine1!',/) ? ? end ? ? subroutine sub2 ? ? write(6,210) ? ? 210 format(t20,' Hello from subroutine2!',/) ? ? end ? ????????????????????????????????????????????????????????????????? 5.9 FORTRAN: Compiling a Program The FORTRAN compiler is invoked with the following command: ????????????????????????????????????????????????????????????????? ? Command Format: f77 ? ????????????????????????????????????????????????????????????????? To compile the above program into an executable program, use the following command at the command line. Sample Session: ????????????????????????????????????????????????????????????????? ? $f77 hello.f ? ? $ ? ????????????????????????????????????????????????????????????????? Without any options, f77 accepts FORTRAN source code and assembly language programs that follow the conventions outlined above. It will compile, assemble, and load these programs to produce an executable called a.out. The f77 utility outputs the object code into files with the same base filename (everything before the period) as the source but with a filename extension of .o. The a.out stands for assembly output. This is the default. Sample Session: ????????????????????????????????????????????????????????????????? ? $f77 hello.f ? ? $a.out ? ? Hello from main! ? ? ? ? Calling function1! ? ? ? ? Hello from function1! ? ? ? ? Back from function1! ? ? ? ? Calling function2! ? ? ? ? Hello from function2! ? ? ? ? Back from function2! ? ? ? ? That's all! ? ? $ ? ????????????????????????????????????????????????????????????????? NOTE: The a.out file that was created by the f77 utility has the following permissions: user - read, write, and execute group - read and execute other - read and execute It is not necessary for you to change the permissions using the chmod command because the f77 utility set the execute permissions for you. 5.10 FORTRAN: Renaming the Executable Module You can rename the executable module using the mv command. The file permissions will be the same as before the file is renamed. Sample Session: ????????????????????????????????????????????????????????????????? ? $mv a.out hello ? ? $hello ? ? Hello from main! ? ? ? ? Calling function1! ? ? ? ? Hello from function1! ? ? ? ? Back from function1! ? ? ? ? Calling function2! ? ? ? ? Hello from function2! ? ? ? ? Back from function2! ? ? ? ? That's all! ? ? $ ? ????????????????????????????????????????????????????????????????? 5.11 FORTRAN: Giving a Name to the Output File It is possible to have the output sent to a file you specify instead of the default, a.out, by using the following command: ????????????????????????????????????????????????????????????????? ? Command Format: f77 -o output source ? ? ? ? output - the name of the executable file ? ? ? ? source - the name of the Fortran source code file ? ????????????????????????????????????????????????????????????????? The -o option tells the f77 utility to tell the link editor to use the specified name for the output instead of the default a.out. NOTE: It is not necessary for the -o option to appear after the f77 command. The filename that appears after the - o is the name of the output file. For example, f77 source -o output is the same as f77 -o output source. Sample Session: ????????????????????????????????????????????????????????????????? ? $f77 -o hello hello.f ? ? $hello ? ? Hello from main! ? ? Calling function1! ? ? ? ? Hello from function1! ? ? ? ? Back from function1! ? ? ? ? Calling function2! ? ? ? ? Hello from function2! ? ? ? ? Back from function2! ? ? ? ? That's all! ? ? $ ? ????????????????????????????????????????????????????????????????? 5.12 FORTRAN: Producing an Assembly Listing This option causes f77 to compile Fortran programs and leave the corresponding assembly language source programs in a file with filename extensions of .s. ????????????????????????????????????????????????????????????????? ? Command Format: f77 -S hello.f ? ? ? ? -S = Compile only ? ????????????????????????????????????????????????????????????????? Sample Session: ????????????????????????????????????????????????????????????????? ? $f77 -S hello.f ? ? $ls -C ? ? example.f hello hex.c octal.c ? ? hello.c hello.s multiply.c ? ? $ ? ????????????????????????????????????????????????????????????????? The file hello.s contains the assembly listing. 5.13 FORTRAN: Main and Two Subroutines in Three Separate Source Files Sample Session: ????????????????????????????????????????????????????????????????? ? $cat main.f ? ? program calling ? ? write(6,100) ? ? 100 format (' Hello from main!',/) ? ? write(6,110) ? ? 110 format(' Calling subroutine1!',/) ? ? call sub1 ? ? write(6,120) ? ? 120 format(t15' Back from subroutine1!',/) ? ? write(6,130) ? ? 130 format(' Calling subroutine2!',/) ? ? call sub2 ? ? write(6,140) ? ? 140 format(t15' Back from subroutine2!',/) ? ? write(6,150) ? ? 150 format(' That's all, folks!') ? ? end ? ? $cat sub1.f ? ? subroutine sub1 ? ? write(6,200) ? ? 200 format(t20,' Hello from subroutine1!',/) ? ? end ? ? $cat sub2.f ? ? subroutine sub2 ? ? write(6,210) ? ? 210 format(t20,' Hello from subroutine2!',/) ? ? end ? ????????????????????????????????????????????????????????????????? 5.14 FORTRAN: Compiling But Not Producing an Executable Module Using the above program, the following command will compile but not produce an executable module. ????????????????????????????????????????????????????????????????? ? Command Format: f77 -c main.f sub1.f sub2.f ? ? ? ? -c = Compile, but do not load object files. This option ? ? causes f77 to compile and/or assemble source code ? ? programs and leave the corresponding object programs ? ? in files with filename extensions of .o. ? ????????????????????????????????????????????????????????????????? Sample Session: ????????????????????????????????????????????????????????????????? ? $f77 -c main.f sub1.f sub2.f ? ? main.f: ? ? MAIN: calling: ? ? sub1.f: ? ? sub1: ? ? sub2.f: ? ? sub2: ? ? $ls a.out *.o ? ? a.out not found ? ? funct1.o ? ? funct2.o ? ? hello.o ? ? main.o ? ? sub1.o ? ? sub2.o ? ? $ ? ????????????????????????????????????????????????????????????????? The -c options causes the compilation system to suppress the link edit phase. This produces an object file or files, in this example (main.o sub1.o sub2.o), that can be link edited at a later time with the f77 command with no options. 5.15 FORTRAN: Compiling Object Files to Produce an Executable Module The command to produce an executable nodule from several object files is done in the following manner: ????????????????????????????????????????????????????????????????? ? Command Format: f77 obj_1 obj_2 obj_3 ? ? ? ? obj_1 through obj_n - the object files ? ????????????????????????????????????????????????????????????????? Sample Session: ????????????????????????????????????????????????????????????????? ? $f77 main.o sub1.o sub2.o ? ? $ls -C ? ? funct1.o funct2.o hello.o main.o sub1.o sub2.o a.out ? ? $ ? ????????????????????????????????????????????????????????????????? 5.16 COBOL: Sample Program with a Main and Two Subroutines Sample Session: ????????????????????????????????????????????????????????????????? ? $cat teacher.cob ? ? identification division. ? ? program-id. teacher. ? ? environment division. ? ? configuration section. ? ? data division. ? ? working-storage section. ? ? procedure division. ? ? begin section. ? ? begin-it. ? ? display " Hello from main!". ? ? display " Calling subroutine1!". ? ? perform subroutine1. ? ? display " Back from subroutine1!". ? ? display " Calling subroutine2!". ? ? perform subroutine2. ? ? display " Back from subroutine2!". ? ? display " That's all, folks!". ? ? stop run. ? ? subroutine1 section. ? ? sub1. ? ? display " Hello from subroutine1!". ? ? subroutine2 section. ? ? sub2. ? ? display " Hello from subroutine2!". ? ????????????????????????????????????????????????????????????????? 5.17 COBOL: Compiling a Program ????????????????????????????????????????????????????????????????? ? Command Format: cobol source_filename ? ????????????????????????????????????????????????????????????????? Three files are created by the compiler. They are identified by the same filename as the source code but with a different extension. They have the extensions .IDY, .INT, and .LST. NOTE: The extensions are uppercase characters. UNIX is case sensitive. Sample Session: ????????????????????????????????????????????????????????????????? ? $cobol teacher.cob ? ? $ls teacher* ? ? teacher.IDY ? ? teacher.INT ? ? teacher.LST ? ? teacher.cob ? ? $ ? ????????????????????????????????????????????????????????????????? 5.18 COBOL: Running a Program ????????????????????????????????????????????????????????????????? ? $cbrun teacher.INT ? ? Hello from Main! ? ? Calling subroutine1! ? ? Hello from subroutine1! ? ? Back from subroutine1! ? ? Calling subroutine2! ? ? Hello from subroutine2! ? ? Back from subroutine2! ? ? That's all, folks! ? ? $ ? ????????????????????????????????????????????????????????????????? NOTES ????????????????????????????????????????????????????????????????? Workshop 5 This workshop will reinforce your understanding of the ideas presented in Chapter 5. Login to the Multimax using the username and password given to you by the instructor. Each student is to complete the entire workshop. DESK EXERCISES 1. "C": What is the command to compile, assemble, and load source code programs? 2. "C": What is the filename extension that indicates a source code program? An assembly language program? An object code file? 3. "C": What is the default filename assigned to the executable file? 4. "C": What command can be used to rename the executable file produced by the cc compiler? What are the file protections associated with the executable? 5. "C": What option will produce an assembly listing? What is the filename extension of this file? Continue on the next page 6. "C": What command will compile the source code program but will not load object files but will keep the object files in files with extensions of .o? 7. FORTRAN: What is the command to invoke the compiler? 8. FORTRAN: What is the filename extension for source code programs? 9. FORTRAN: What is the name of the default executable file? 10. FORTRAN: How can you change the permissions on the executable module so anyone can execute it? 11. FORTRAN: What option on the call to the compiler will allow you to specify the name of the executable file? Continue on the next page 12. FORTRAN: What option on the call to the compiler will produce an assembly listing? What is the filename extension of this file? 13. FORTRAN: What option will produce object modules but not produce an executable module? 14. FORTRAN: What command will produce an executable module from several object modules? 15. COBOL: What is the command to call the compiler? 16. COBOL: What are the three files created by the compiler? What are the filename extensions? 17. COBOL: Which of the three files that have been created are used to run the program? Continue on the next page COMPUTER EXERCISES 18. Copy the following files from /user0/teacher: main.c funct1.c funct2.c Are these programs "C", FORTRAN, or COBOL? Compile these three files creating an executable file called main1.exe and then execute it. What are the file protections? Why? 19. Now append the three files into one file. Use output redirection. Compile the file creating the executable file called main2.exe . Execute main2.exe. 20. Copy the following files from /user0/teacher: main.f sub1.f sub2.f Compile these three files creating an executable file called main1.exe . Execute main1.exe 21. Now append the three files into one file. Compile the file creating the executable file called main2.exe . Execute main2.exe. 22. COBOL: Copy teacher.cob from /user0/teacher. Compile and run it. NOTES ????????????????????????????????????????????????????????????????? NOTES ????????????????????????????????????????????????????????????????? 6. UNIX TOOLS 6.1 Processes A process is the execution of a command by UNIX. Processes can also be executed by the operating system itself. Like the file structure, the process structure is hierarchical. It contains parents, children, and even a root. A parent can fork (or spawn) a child process. That child can, in turn, fork other processes. The first thing the operating system does to begin execution is to create a single process, PID number 1. PID stands for Process IDentification. This process will hold the same position as the root directory in the file structure. This process is the ancestor to all processes that each user works with. It forks a process for each terminal. Each one of these processes becomes a Shell process when the user logs on. 6.2 Executing a Command When you give a command to the Shell, it will fork a process to execute the command. While the child process is executing the command, the parent will go to sleep. Sleeping means that the process will not use any CPU time. It remains inactive until it is awakened. When the child process has finished executing the command, it dies. The parent process, which is running the Shell, wakes up and prompts you for another command. When you request a process to run in the background (by ending the command line with an &), the Shell forks a child process that is allowed to run to completion. The parent process will report the PID of the child process and them prompts you for another command. The child and parent are now independent processes. 6.3 Process Identification The Unix operating system assigns a unique process identification number (PID) to each process. It will keep the same PID as long as the process is in existence. During one session, the same process is always executing the login Shell. When you execute another command a new process is forked and a new PID is assigned to that process. When that child process is finished you are returned to the login process, which is running the Shell, and that parent process has the same PID as when you logged on. The Shell stores the PID in Shell variable called $. The PID can also be shown with the process status (ps) command. The format for ps is as follows: ????????????????????????????????????????????????????????????????? ? Command Format: ps [options] ? ? ? ? See on-line manual for options ? ????????????????????????????????????????????????????????????????? With no options given the ps command will give you certain information about processes associated with the controlling terminal. The output consists of a short listing containing the process id, terminal id, cumulative execution time, and the command name. Otherwise, options will control the display. Sample session: ?????????????????????????????????????????????????????????????????????????????? ? $echo $ ? ? 8347 ? ? $ps ? ? PID TTY TIME COMMAND ? ? 8347 rt021a0 0:03 ksh ? ? 8376 rt021a0 0:06 ps ? ? $ ? ?????????????????????????????????????????????????????????????????????????????? The PID numbers of the Shell are the same in the sample session because the shell will substitute its own PID number for $. The Shell makes the substitution before it forks a new process to execute the echo command. Therefore, echo will display the PID number of the process that called it, not the PID of the process that is executing it. The -l option will display more information about the processes. Sample Session: ???????????????????????????????????????????????????????????????????????????????????????????? ? $ps -l ? ? F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME COMD ? ? f0000 S 115 8347 309 2 30 20 1009000 140 94014 rt021a0 0:03 ksh ? ? f0000 O 115 8386 8347 16 68 20 1308000 72 rt021a0 0:01 ps ? ? $ps -l ? ? F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME COMD ? ? f0000 S 115 8347 309 1 30 20 1009000 140 94014 rt021a0 0:03 ksh ? ? f0000 O 115 8387 8347 26 73 20 1146000 72 rt021a0 0:01 ps ? ? $ ? ???????????????????????????????????????????????????????????????????????????????????????????? 6.4 grep: A Pattern Matching Filter The grep utility can search through a file to see if it contains a specified string of characters. The utility will not change the file it searches but displays each line that contains the string. The format for the string is: ?????????????????????????????????????????????????????????????????????????????? ? Command Format: grep [options] limited_regular-expression [file] ? ? ? ? Use the man command for a complete list of options ? ? ? ?????????????????????????????????????????????????????????????????????????????? The grep utility searches files for a pattern and displays all lines that contain the pattern. It uses limited-regular- expressions (these are expressions that have string values that use a subset of all the possible alphanumeric and special characters) like those used with ed to match the patterns. Be careful using the characters $, *, [, ^, |, (, ), and \ in the regular expression because they will be evaluated by the shell. It is good practice to enclose the regular expression in single quotes. This will prevent the shell from evaluating these special characters. The grep utility will assume standard input if no files are given. Normally, each line found in the file will be displayed to standard output. Sample session: ................................................................. . $grep 'disc' memo . ................................................................. This command will search the file "memo" for the string "disc". It will include words like discover and indiscreet because they contain the characters "disc". The single quote marks are not necessary and for this example they wouldn't have made any difference. They do allow you to include spaces in the search pattern. 6.4.1 More on Regular Expressions The grep command can be best understood by a discussion of regular expressions. Let's create a database of phone numbers called phone.lis and then use regular expressions to search through the database. Here is as listing of the contents of phone.lis Sample session: ????????????????????????????????????????????????????????????????? ? $cat phone.lis ? ? Smith, Joan 7-7989 ? ? Adams, Fran 2-3876 ? ? StClair, Fred 4-6122 ? ? Jones, Ted 1-3745 ? ? Stair, Rich 5-5972 ? ? Benson, Sam 4-5587 ? ? $ ? ????????????????????????????????????????????????????????????????? The format for the records in this database is: Last name, First name <tab> #-#### Using the database (phone.lis) above. What grep command would we use to search through the database and get all the records that had a person whose name contains an "S". An alphabetic character represents itself. Sample session: ????????????????????????????????????????????????????????????????? ? $grep S phone.lis ? ? Smith, Joan 7-7989 ? ? StClair, Fred 4-6122 ? ? Stair, Rich 5-5972 ? ? Benson, Sam 4-5587 ? ? $ ? ????????????????????????????????????????????????????????????????? This grep command searched for the string "S" and then listed all the lines in phone.lis that matched. A single . (dot) is used to represent any single character. Sample session: ????????????????????????????????????????????????????????????????? ? $grep .S phone.lis ? ? Benson, Sam 4-5587 ? ? $ ? ????????????????????????????????????????????????????????????????? A $ represents the end of the line. Sample session: ????????????????????????????????????????????????????????????????? ? $grep 5$ phone.lis ? ? Jones, Ted 1-3745 ? ? $ ? ????????????????????????????????????????????????????????????????? A ^ represents the beginning of the line Sample session: ????????????????????????????????????????????????????????????????? ? $grep ^S phone.lis ? ? Smith, Joan 7-7989 ? ? StClair, Fred 4-6122 ? ? Stair, Rich 5-5972 ? ? $ ? ????????????????????????????????????????????????????????????????? Regular expressions must get to grep in order for them to be evaluated properly. Let's say we want to get the records of employees that have a phone number that begins with a "4". What does the following expression do? Sample session: ????????????????????????????????????????????????????????????????? ? $grep <tab>4 phone.lis ? ? StClair, Fred 4-6122 ? ? Jones, Ted 1-3745 ? ? Benson, Sam 4-5587 ? ? $ ? ????????????????????????????????????????????????????????????????? Why did we get the record of Ted Jones? The tab character was evaluated by the shell and so the search was actually made looking for a "4". This is the same as if we had entered $grep 4 phone.lis. We must prevent the shell from evaluating these characters, this is done with the \ (backslash) character as shown in the next example. Sample session: ????????????????????????????????????????????????????????????????? ? $grep \<tab>4 phone.lis ? ? StClair, Fred 4-6122 ? ? Benson, Sam 4-5587 ? ? $ ? ????????????????????????????????????????????????????????????????? Now it worked properly. It searched for a <tab> character followed by the number 4. The [] (left and right brackets) are used to identify a range of characters. Sample session: ????????????????????????????????????????????????????????????????? ? $grep \[AF] phone.lis ? ? Adams, Fran 2-3876 ? ? StClair, Fred 4-6122 ? ? $ ? ????????????????????????????????????????????????????????????????? Why do [] need to be quoted? In the previous example the search makes a match on "A" or "F" . A - (dash) can indicate inclusion. For example, we want to make a match on a phone number that has a 1, 2, 3, or 4. How can this be done? Here's an example: Sample Session: ????????????????????????????????????????????????????????????????? ? $grep \[1-4] phone.lis ? ? Adams, Fran 2-3876 ? ? StClair, Fred 4-6122 ? ? Jones, Ted 1-3745 ? ? Stair, Rich 5-5972 ? ? Benson, Sam 4-5587 ? ? $ ? ????????????????????????????????????????????????????????????????? A ^ character looks for all characters NOT inside the [] brackets. For example, [^0-9] matches all non-digits [^a-zA-Z] matches all non-alphabetic characters Note: \, *, and $ lose their meta-character meanings inside the []. Also the ^ character is special only if it appears first. What is the following command searching for? Sample Session: ????????????????????????????????????????????????????????????????? ? $grep '[^789]