Notes
on Shell Programming
Special
Parameters
$#
The
number of arguments passed to the program; or the number of
parameters set by executing the set statement
$*
Collectively
references all the positional parameters as $1, $2, ...
$@
Same
as $*, except when double-quoted ("$@") collectively
references all the positional parameters as "$1", "$2",
...
$0
The
name of the program being executed
$$
The
process id number of the program being executed
grep
-v "$name" phonebook > /tmp/phonebook$$
$!
The
process id number of the last program sent to the background for
execution
$?
The
exit status of the last command not executed in the background
$-
The
current option flags in effect
Other
Variables Used by the Shell Variable
CDPATH
The
directories to be searched whenever cd is executed without a full
path as argument.
ENV
The
name of a file that the shell executes in the current environment
when started interactively.
FCEDIT
The
editor used by fc. If not set, ed is used.
HISTFILE
If
set, it specifies a file to be used to store the command history. If
not set or if the file isn't writable, $HOME/.sh_history is used.
HISTSIZE
If
set, specifies the number of previously entered commands accessible
for editing. T
HOME
IFS
The
Internal Field Separator characters; used by the shell to delimit
words when parsing the command line, for the read and set commands,
when substituting the output from a back-quoted command, and when
performing parameter substitution. Normally, it contains the three
characters space, horizontal tab, and newline.
PATH
PPID
The
process id number of the program that invoked this shell (that is,
the parent process).
PS1: The
primary command prompt, normally "$ ".
PS2: The
secondary command prompt, normally "> ".
PWD
Parameter
Substitution
$parameter
or ${parameter}
To
access the tenth and greater arguments, you must write ${10}.
shift
whatever
was previously stored inside $2 will be assigned to $1, The old value
of $1 will be irretrievably lost. When this command is executed, $#
(the number of arguments variable) is also automatically decremented
by one.
You
can shift more than one "place" at once by writing a count
immediately after shift, as in
shift
3
${parameter:-value}
Substitute
the value of parameter if it's set and non-null; otherwise,
substitute value.
${parameter-value}
Substitute
the value of parameter if it's set; otherwise, substitute value.
${parameter:=value}
Substitute
the value of parameter if it's set and non-null; otherwise,
substitute value and also assign it to parameter.
${parameter=value}
Substitute
the value of parameter if it's set; otherwise, substitute value and
also assign it to parameter.
${parameter:?value}
Substitute
the value of parameter if it's set and non-null; otherwise, write
value to standard error and exit. If value is omitted, write
parameter: parameter null or not set instead.
${parameter?value}
Substitute
the value of parameter if it's set; otherwise, write value to
standard error and exit. If value is omitted, write parameter:
parameter null or not set instead.
${parameter:+value}
Substitute
value if parameter is set and non-null; otherwise, substitute null.
${parameter+value}
Substitute
value if parameter is set; otherwise, substitute null.
${#parameter}
Substitute
the length of parameter. If parameter is * or @, the result is not
specified.
${parameter#pattern}
Substitute
the value of parameter with pattern removed from the left side. The
smallest portion of the contents of parameter matching pattern is
removed. Shell filename substitution characters (*, ?, [...], !, and
@) may be used in pattern.
${parameter##pattern}
Same
as #pattern except the largest matching pattern is removed.
${parameter%pattern}
Same
as #pattern except pattern is removed from the right side.
${parameter%%pattern}
Same
as ##pattern except the largest matching pattern is removed from the
right side. Quoting
'…' Removes
special meaning of all enclosed characters
"…" Removes
special meaning of all enclosed characters except $, `, and \
\c
Removes
special meaning of character c that follows; inside double quotes
removes special meaning of $, `, ", newline, and \that follows,
but is otherwise not interpreted; used for line continuation if
appears as last character on line (newline is removed)
Using
the Backslash for Continuing Lines
The
Backslash Inside Double Quotes
The
backslash inside these quotes removes the meaning of characters that
otherwise would be interpreted inside double quotes (that is, other
backslashes, dollar signs, back quotes, newlines, and other double
quotes). If the backslash precedes any other character inside double
quotes, the backslash is ignored by the shell and passed on to the
program:
Command
Substitution
The
Back Quote `command`
The
$(...) Construct $(command)
variable=$(command)
The
expr Command(for older linux)
expr
10 + 20 / 2
Each
operator and operand given to expr must be a separate argument,
expr
17 * 6
The
shell saw the * and substituted the names of all the files in your
directory!
expr
17 \* 6
only
use the command substitution mechanism to assign the output from expr
back to the variable:
$
i=$(expr $i + 1) Add 1 to i
like
the shell's built-in integer arithmetic, expr only evaluates integer
arithmetic expressions. You can use awk or
bc if you need to do floating point calculations.
Decisions
user="$1"
if
who | grep "^$user " > /dev/null
then
echo
"$user is logged on"
fi
if
command
then
command
else
command
fi
if
command
then
command
elif
command2
then
elif
commandn
then
else
fi
The
test Command
test
String Operators
Operator Returns
TRUE (exit status of 0) if
string1
= string2, string1 != string2, string
-n
string
string
is not null (and string must be seen by test).
-z
string
string
is null (and string must be seen by test).
An
Alternative Format for test
[
expression ]
spaces
must appear after the [ and before the ].
[
"$name" = julio ]
Integer
Operators
int1
-eq int2
int1
-ge int2
int1
-gt int2
int1
-le int2
int1
-lt int2
int1
-ne int2
File
Operators
-d
file file is a directory.
-e
file file exists.
-f
file file is an ordinary file.
-r
file file is readable by the process.
-s
file file has nonzero length.
-w
file file is writable by the process.
-x
file file is executable.
-L
file file is a symbolic link.
The
Logical Negation Operator !
The
Logical AND Operator –a
The
Logical OR Operator –o
[
-f "$mailfile" -a -r "$mailfile" ]
Parentheses
Use
parentheses in a test expression to alter the order of evaluation;
and make sure that the parentheses are quoted because they have a
special meaning to the shell.
[
\( "$count" -ge 0 \) -a \( "$count" -lt 10 \) ]
The
exit Command
The
case Command
hour=$(date
+%H)
case
"$hour"
in
0?
| 1[01] ) echo "Good morning";;
1[2-7]
) echo "Good afternoon";;
*
) echo "Good evening";;
esac
The
-x Option for Debugging Programs
You
can trace the execution of any program by typing sh -x followed by
the name of the program.
The
Null Command :
The
&& and || constructs implement shortcut logic
enable
you to execute a command based on whether the preceding command
succeeds or fails.
sort
bigdata > /tmp/sortout && mv /tmp/sortout bigdata
[
-z "$EDITOR" ] && EDITOR=/bin/ed
grep
"$name" phonebook || echo "Couldn't find $name"
The
for Command
for
i in 1 2 3
do
echo
$i
done
The
$@ Variable
Whereas
the shell replaces the value of $* with $1, $2, ..., if you instead
use the special shell variable "$@" it will be replaced
with "$1", "$2", ... .
The
for Without the List
for
var
do
command
done
Shell
automatically sequences through all the arguments typed on the
command line, just as if you had written
for
var in "$@"
do
command
done
The
while Command
The
while loop is often used in conjunction with the shift command to
process a variable number of arguments typed on the command line.
while
[ "$#" -ne 0 ]
do
echo
"$1"
shift
done
The
until Command
until
who | grep "^$user " > /dev/null
do
sleep
60
done
break
When
the break is executed, control is sent immediately out of the loop,
where execution then continues as normal with the command that
follows the done.
break
n the n innermost loops are immediately exited.
continue
n causes the commands in the innermost n loops to be
skipped; but execution of the loops then continues as normal.
Executing
a Loop in the Background
An
entire loop can be sent to the background for execution simply by
placing an ampersand after the done.
for
file in memo[1-4]
do
run
$file
done
&
I/O
Redirection on a Loop
Input/Output
redirected into the loop applies to all commands in the loop that
read their data from standard input or write to standard output.you
can also redirect the standard error output from a loop, simply by
tacking on a 2> file after the done.
You
can override redirection of the entire loop's input or output by
explicitly redirecting the input and/or output of commands inside the
loop. To force input or output of a command to come from or go to the
terminal, use the fact that /dev/tty always refers to your terminal.
for
file
do
echo
"Processing file $file" > /dev/tty
done
> output
Piping
Data Into and Out of a Loop
A
command's output can be piped into a loop, and the entire output from
a loop can be piped into another command in the expected manner.
for
i in 1 2 3 4
do
echo
$i
done
| wc -l
Typing
a Loop on One Line
for
i in 1 2 3 4; do echo $i; done
if
commands can also be typed on the same line using a similar format:
if
[ 1 = 1 ]; then echo yes; fi
The
getopts Command
getopts
options variable
The
getopts command is designed to be executed inside a loop. Each time
through the loop, getopts examines the next command line argument and
determines whether it is a valid option. This determination is made
by checking to see whether the argument begins with a minus sign and
is followed by any single letter contained inside options. If it
does, getopts stores the matching option letter inside the specified
variable and returns a zero exit status.
If
the letter that follows the minus sign is not listed in options,
getopts stores a question mark inside variable before returning with
a zero exit status. It also writes an error message to standard
error.
If
no more arguments are left on the command line or if the next
argument doesn't begin with a minus sign, getopts returns a nonzero
exit status.
To
indicate to getopts that an option takes a following argument, you
write a colon character after the
option letter on the getopts command line.
getopts
mt: option
If
getopts doesn't find an argument after an option that requires one,
it stores a question mark inside the specified variable and writes an
error message to standard error. Otherwise, it stores the actual
argument inside a special variable called OPTARG.
Another
special variable called OPTIND is
initially set to one and is updated each time getopts returns to
reflect the number of the next command-line argument to be processed.
while
getopts mt: option
do
case
"$option"
in
m)
mailopt=TRUE;;
t)
interval=$OPTARG;;
\?)
echo "Usage: mon [-m] [-t n] user"
exit
1;;
esac
done
shiftcount=$((OPTIND
– 1))
shift
$shiftcount
user=$1
Reading
and Printing Data
The
read Command read variables
You
can use the –r option to read to prevent shell interpreting the
backslash character.
while
read –r line
Special
echo Escape Characters \c
\c
tells echo to leave the cursor right where it is after
displaying the last argument and not to go to the next line.
The
printf Command
printf
"format" arg1 arg2 ...
printf
Conversion Specification Modifiers
- Left
justify value.
+ Precede
integer with + or -.
(space) Precede
positive integer with space character.
# Precede
octal integer with 0, hexadecimal integer with 0x or 0X.
Width Minimum
width of field; * means use next argument as width.
Precision
Minimum
number of digits to display for integers; maximum number of
characters to display for strings; * means use next argument as
precision.
More
on Subshells
A
subshell can't change the value of a variable in a parent shell, nor
can it change its current directory.
The
. Command
Its
purpose is to execute the contents of file in the current shell, A
subshell is not spawned to execute the program.
The
(...) and { ...; } Constructs
They
are used to group a set of commands together.
The
first form causes the commands to be executed by a subshell, the
latter form by the current shell.
For
{}., if the commands enclosed in the braces are all to be typed on
the same line, a space must follow the left brace, and a semicolon
must appear after the last command.
.profile
File
/etc/profile
and $HOME/.profile
I/O
Redirection
<
file, > file
>|
file
Redirect
standard output to file; file is created if it doesn't exist and
zeroed if it does; the noclobber (-C) option to set is ignored.
>>
file
Like
>, only output is appended to file if it already exists.
Redirect
the standard output for a command to standard error by writing
command
>& 2
Collect
the standard output and the standard error output from a program into
the same file.
command
>foo 2>>foo or command >foo
2>&1
Because
the shell evaluates redirection from left to right on the command
line, the last example cannot be written: command 2>&1 >
foo
Inline
Input Redirection
command
<<word
word
the
shell uses the lines that follow as the standard input for command,
until a line that contains just word is found.
The
shell performs parameter substitution for the redirected input data,
executes back-quoted commands, and recognizes the backslash
character. However, any other special characters, such as *, |, and
", are ignored. If you have dollar signs,
back quotes, or backslashes in these lines that you don't want
interpreted by the shell, you can precede them with a backslash
character. Alternatively, if you want the shell to leave the input
lines completely untouched, you can precede the word that follows the
<< with a backslash.
If
the first character that follows the << is a dash (-), leading
tab characters in the input will be removed by the shell.
<&
digit Standard input is redirected from the file
associated with file descriptor digit.
>&
digit Standard output is redirected to the file associated
with file descriptor digit.
<&- Standard
input is closed.
>&- Standard
output is closed.
<>
file Open file for both reading and writing.
Shell
Archives
One
or more related shell programs can be put into a single file and then
shipped to someone.
cat
> program_name <<\THE-END-OF-DATA
THE-END-OF-DATA
The
exec Command
Because
the exec'ed program replaces the current one, there's one less
process hanging around; also, startup time of an exec'ed program is
quicker, due to the way the Unix system executes processes.
exec
can be used to close standard input and reopen it with any file that
you want to read. To change standard input to file:
exec
< file
Redirection
of standard output is done similarly: exec >
report
If
you use exec to reassign standard input and later want to reassign it
someplace else, you can simply execute another exec. To reassign
standard input back to the terminal, you would write
exec
< /dev/tty
The
set Command
General
Format: set options args
This
command is used to turn on or off options as specified by options. It
is also used to set positional parameters, as specified by args.
Each
single letter option in options is enabled if the option is preceded
by a minus sign (-), or disabled if preceded by a plus sign (+).
set
Options
--
--
option tells set not to interpret any subsequent arguments on the
command line as options. It also prevents set from displaying all
your variables if no other arguments follow.
-a
Automatically
export all variables that are subsequently defined or modified.
-v
Print
each shell command line as it is read.
-x
Print
each command and its arguments as it is executed,
set
with No Arguments
Using
set to Reassign Positional Parameters
There
is no way to directly assign a value to a positional parameter;
These
parameters are initially set on execution of the shell program. The
only way they may be changed is with the shift or the set commands.
If words are given as arguments to set on the command line, those
words will be assigned to the positional parameters $1, $2, and so
forth. The previous values stored in the positional parameters will
be lost forever. So
set
a b c
assigns
a to $1, b to $2, and c to $3. $# also gets set to 3.
The
IFS Variable stands for Internal Field Separator.
echo
"$IFS" | od -b
The
readonly Command
readonly
–p gets a list of your read-only variables
The
unset Command
unset
x Remove x from the environment
This
causes the shell to erase definitions of the variables or functions
listed in names. Read-only variables cannot be unset. The –v
option to unset specifies that a variable name follows, whereas
the –f option specifies a function name. If neither
option is used, it is assumed that variable name(s) follow.
The
eval Command
eval
command-line
the
net effect is that the shell scans the command line twice before
executing it.
pipe="|"
ls
$pipe wc -l
The
shell takes care of pipes and I/O redirection before variable
substitution, so it never recognizes the pipe symbol inside pipe.
eval
ls $pipe wc –l
The
first time the shell scans the command line, it substitutes | as the
value of pipe. Then eval causes it to rescan the line, at which point
the | is recognized by the shell as the pipe symbol.
Get
the last parameter: eval echo \$$#
The
wait Command
wait
process-id
where
process-id is the process id number of the process you want to wait
for. If omitted, the shell waits for all child processes to complete
execution.
The
trap Command
trap
commands signals
Commonly
Used Signal Numbers
0 Exit
from the shell
1 Hangup
2 Interrupt
(for example, Delete, Ctrl+c key)
15 Software
termination signal (sent by kill by default)
trap
"rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 1 2
The
value of WORKDIR and $$ will be substituted at the time that the trap
command is executed. If you wanted this substitution to occur at the
time that either signal 1 or 2 was received (for example, WORKDIR may
not have been defined yet), you can put the commands inside single
quotes:
trap
'echo logged off at $(date) >>$HOME/logoffs' 0
trap
'rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit' 1 2
trap
with No Arguments
Executing
trap with no arguments results in the display of any traps that you
have changed.
Ignoring
Signals
If
the command listed for trap is null, the specified signal will be
ignored when received.
trap
"" 2
If
you ignore a signal, all subshells also ignore that signal. However,
if you specify an action to be taken on receipt of a signal, all
subshells will still take the default action on receipt of that
signal.
If
you execute trap : 2
and
then execute your subshells, then on receiving the interrupt signal
the current shell will do nothing (it will execute the null command),
but all active subshells will be terminated (they will take the
default action—termination).
Resetting
Traps
After
you've changed the default action to be taken on receipt of a signal,
you can change it back again with trap if you simply omit the first
argument;
trap
1 2
Functions
name
() { command; ... command; }
Removing
a Function Definition
To
remove the definition of a function from the shell, you use the unset
command with the –f option.
unset
–f nu
Material
Unix
Shell Programming, Third Edition