IT 244 – Chapter 10 Programming the Bourne Again Shell: Part1 – Overview Debugging Shell Scripts o Place echo statements along the way. o Use the –x bash option bash –x yourScript arglist This prints a trace: which is a printout of each command before it actually runs it. All expansions will already have been done before the line is printed. The PS4 prompt is used to show command line printouts, so this can be set to make it obviously different to program output. Control Structures o if, if/then, if/then/else, if/then/else/elif o for, for in, o while (do done), until (do done) o case o break, continue Input during a run o select, uses the PS3 variable as prompt o Here document – uses redirection – double less than with begin and end characters – text is all “here” o File descriptors exec n> outfile, or duplicate another by exec n>&m exec m< infile, or duplicate another by exec m<&n Close using exec n>&-, or exec m<&Functions – rehashed o Function funcName() { <functionBody> } o Call this from anywhere in the script, whether outside of a function, in another function, or a function calling itself, by giving the function name. o Arguments are passed just as on the command line. If you have a variable with a space-delimited string, that can be given as the argument, and set will automatically be called on it to produce $1 - $n. Parameters and Variables o Local vs global The default is local. No child process can see the variable. export makes a variable global, in that the value of the variable will be copied to any child processes The child making a change does not reflect with the parent copy. Functions are not processes, so they have access to variables even if they are not defined within their own block. No need for them to be exported. Whether a variable is local or global, bash makes sure that any variables in your script will not conflict with variables in another script that uses yours, since it does not allow the child process to change the value of a variable owned by the parent. Functions can have local variables by using the declare or typeset command. o A variable or parameters can be used to run a command merely by preceding it with a $ as the first token on a command line. o Parameters: Special Parameters: $$ – PID# for this process $? – Exit status of the last command Positional Parameters: $# – Number of command line arguments. $0 – Name of this calling program (script) o The exact relative or absolute path used to make the call (except ~ is substituted by full path) $1 - $n – Command line arguments o Any larger than $9 must be surrounded by curly braces ( ${10} ) o shift – Command to shift arguments one to the left (promotes arguments). o set – Can be used to initialize command line arguments Combining command substitution or pathname expansion with set. Convenient way to get input data. $* and $@ – Represent all command line arguments o One is a space delimited string, and the other is an array. (See issue on p444) Expanding null and unset variables – expands to a null string. You can: o Use a default value ( :- ) - Uses but doesn’t assign ${name:-defaultVal} o Assign a default value ( := ) - Uses and assigns ${name:=defaultVal) In both cases, defaultVal can contain variables and other expansions. To use the assign without actually setting the value into something else, start the command with a : and a space – ( : ${name:=defaultVal} ). Otherwise, you must use this as an expansion o Display an error message ( :? ) ${name:?someErrorMsg} Some Built-ins o type – Gives the type of a command, whether builtin or not, and whether hashed or not. Also gives the path if not builtin. If the string is a shell keyword, like if, or an alias, this will also be reported. Note: type tells whether a command is hashed. What this means is that a non-builtin command, when called the first time, is searched for using the PATH variable. The path is then plugged into a hash table, with the name of the command as the key, so that the next time the command is called, the shell will know where to look. This plugging of the hash happens the first time for each session. o read Without the –p option, you echo a prompt (using –n) and then call read followed by a variable name. read the waits for keyboard input and places that into the variable. It waits for a newline to retrieve the value. read also has a –p option that takes a prompt string an then waits for keyboard input after printing the prompt. If you give more than one variable on the read command line, it was read each token (delimited by the given character(s)) into each variable. If there are less variables than tokens, it will fill the last one with the rest, separated by one space, no matter how many spaces were on the command line. Options: -a aname - Will create an array called aname of all tokens read. -d delim – Will change the input termination delimeter from newline to delim. This means that, instead of waiting for the newline in order to assign values to the variables given, the input will be immediately assigned when the alternate delimiter is received. Therefore, if there is only one token before the alternate delimiter, no more than one variable will be assigned to. o A subsequent read will then get the next string from the keyboard if it exists. -n num - Read that number of characters and then returns. o A subsequent read will then get the next string from the keyboard if it exists. - p prompt – Prints a prompt and waits for keyboard input. -s – silent so that it will not echo input back to the display. This can be used for password entry. o exec o trap -u n – sets n as the file descriptor for read to take input from. Executes commands or redirects file descriptors Command Execution: exec command argList Overlays the current process space with the new command. The current process will terminate execution, and the newly overlayed command (or shell script) will begin execution in that space. File Descriptor Redirects: exec < infile, or exec > outfile - Redirecting standard in and out, and opens infile or outfile for input or output. exec n< infile or exec m> outfile – Creates new file descriptors and opens infile or outfile for input or output. Catch a system signal You can use this to make sure Ctrl-C, Ctrl-D, Ctrl-Z, and other system signals do not stop your process. Or to clean up properly before stopping. Expression evaluation o Arithmetic let <arithmetic assignment expression> This allows for assigning a value from an expression on the right hand side of an “=” operator to a variable on the left hand side. o Example: let a=a+1 o Note: there can be no spaces in the assignment expression. o Note: to put more than one assignment in a let statement, separate them with a space. Example: let a=a+1 b=b-3 c=a+b ((<arithmetic assignment expression>)) This is a type of shorthand for the let statement above. o Example: (( a=a+1 )) o Note: to put more than one assignment in side the double-parenthesis operators, separate them using a comma. Example: (( a=a+1, b=b-3, c=a+b )) o Logical (Conditional) [[ <conditional statement ]] Conditional statements evaluate whether the value of the left side of a “=” operator is the same as, not the same as, less than, or greater than the value of the right side. Example: [[ $a = $b ]] You can evaluate more than one conditional by using the && operator (AND) or the || operator (OR) Example: [[ $a = $b && $a = $c ]]