You are on page 1of 14

Shell Script Programming

You are the 1252902nd visitor to this page since March 20, 2001.

This is a document that covers some issues regarding shell script programming. Note that this page is still under construction. The intension is that is should be possible to use it as a WWW text for "advanced" shell programming, but right now I am just collecting stuff. Note! I use Bourne shell or derivatives thereof, like BASH. Therefore the scripts contained herein is written for Bourne shell (usually found under /bin/sh), unless said otherwise. Also not that this is work in progress. Hence some of the descriptions might be bad, some might be confusing and yet some may be missing. If that is the case, please send me a note about it. This document is structured as follows.
1. Introduction

2. Giving commands to the shell o Simple commands o Shell Variables & Shell Expansion  The PATH variable  Other predefined variables 3. One-liners o Renaming several files at the same time o Find the full name of a user o Remove processes matching some regular expression o Remove executable files that has a corresponding C-file o Finding programs matching a wild card o Verifying a set of e-mail addresses 4. Tips & Tricks o Generating commands for sh o Splitting a line using read o Splitting a line at arbitrary characters by redefining IFS o Setting a variables for one command only o Feeding a script through standard input o The use of pipes 5. Exercises 6. Examples of scripts

the shell is a pretty complete programming language." On a UNIX system such a program is called the shell (in contrast with the core that contains time-sharing code. delivered the pack to the computer department. A better approach would be to have a small set of processing programs together with a program made to "glue the parts together. It is no longer enough to be able to load your program and just print the result. redirect input and output. It would of course be possible to write specially designed programs that formatted the output of your programs according to your wishes. but the number of specialized programs would quickly increase. The shell is used to issue commands. control jobs. Modern computers are a little more complex than that. You punched your program on cards. file access code and other system oriented code). leaving your computer loaded with "might come in handy" programs. executed it and retrieved the result on paper. The staff there loaded the program into the computer. Not only that. You there have a complete environment where you can execute your programs and even have such astonishing things as interactive programs (hear-hear). You also need support to reformat the results. We will start from the beginning. This was in turn returned to you and you had to sit down and figure out why you got the result you got. process them in other manners (maybe printing a nice diagram) and store them in a database. and other mundane things that you do on a modern computer. Complete Scripts o Removing unwanted file from a directory tree o CGI to the UNIX command man o A collection of BASH functions o Program to count space occupied by "garbage" o Program to print booklets from DVI-files o Program that takes measurements on execution time of a script and produces a calc script to do a least-squares approximation to the function a * n + b * n * log(n) + c. Introduction In the early days computers where used to run programs.o Finding all executable programs in your path 7. In this paper we will introduce concepts and methods that a good shell-programmer can use to get the most out of his/her UNIX system. and nothing more. start processes. .

together with some of the standard ones. although you are welcome to read the paper. A simple command is a sequence of non-blank words separated by blanks. We will start by going through the process of executing a simple program. we have the following definition of simple commands. echo. i. Giving commands to the shell There are basically two types of commands: simple commands and complex commands. you just type man followed by the command you want information on. If you for some reason lack a prompt. The man command is one of the more useful. $ is the prompt. you will not be able to give commands to the shell. Except as specified below. The command name is passed as argument 0 (see execve(2V)). There are many more simple commands that are useful. For example. the remaining words are passed as arguments to the invoked command. to execute the simple command ls you do the following. i. a description of what the command does. To get information on how to use a command. to get information on rm you type $ man rm . To execute a simple command you simply type it to the shell. In this section we will explain what simple commands are and go through the complex commands one by one.but a basic familiarity with programming and/or the basic principles of computers will be assumed. cat. and possible variations of its use. This is not an paper for the complete novice. It is used to get a manual of a command. There are many possible reasons to why you may not have a prompt. We will in the sequel print the text that the computer prints in 'Courier' and the text that you type to the computer in 'boldface Courier'. ls is the command you type to the computer and the remaining lines are the result of the ls command. Simple commands From the manual of sh(1). Some examples are: man. the text the computer prints to tell you that it is ready to accept commands.e.e. $ ls Mail News outgoing doc emacs incoming lib man tmp public_html bin In this example.g. e. The first word specifies the name of the command to be executed. and then continue by investigating the steps in the execution more throughly. and rm.

Example: If your path contains `/usr/bin:/bin:/usr/local/bin' you may extend the path with /home/matkin/bin (which could be the place where you put your own scripts) by writing $ PATH=/home/matkin/bin:$PATH . . the shell searches for a program to execute. The path variable controls where the shell searches for commands. If you type cd without any arguments. this is the directory where you will end up. Let us go through the process in detail. Since we don't want to go through all files in the file system (on my account alone.and the result will be a manual of how the command rm works and what it does. It is entirely up the the type of shell that you are using. return. Shell Variables & Shell Expansion There is a set of predefined variables in the shell. just alter the value of PATH. we have a path of directories where the program may be stored. Pascal. they are executable either because they are compiled programs (written in C. Try the above command. C++. A simple example of a variable is the HOME variable. The programs are simply executable files somewhere in the file system. Exercise. which contains the path to your home directory (where you end up when you log in). pwd. To print the value of the variable HOME. trap. cd. when you type them to at the prompt. (or alternativelysource). There is a special set of commands that are built into the shell. you can write the following: $ echo $HOME /users/matkin The PATH variable One of the more important variables is the path variable. hash. When you type a non-builtin command to the shell. To change the directories where your shell should look. What does the rm command do? How should you use it? Give at least 2 examples of use. The more common builtin commands are: echo. or some other language) or because they are scripts that may be executed. I have approximately 3700 files). These variables are used to store values and also to change the behavior of called programs. Buildin simple commands. and kill. Ada. This path is given to the shell as a colon separated list of directories stored in the environment variable PATH. eval.

IFS This is set to the internal field separators. you have to add a line to the startup file. your changes will be undone since every time you start a new shell: each shell starts with a fresh set of variables. normally set to space. We will here go through the more important ones and describe their purpose. PS2 The secondary prompt string. Note! It is very common to put . If you log out. This is highly insecure and you should never do that. normally set to `$ '. We will talk more about this later. normally set to `> '. To set the path each time you log in..g. e. Other predefined variables There is a set of other predefined variables used for different purposes related to the behaviour of the shell. Since we are not ready to give the complete figure of what happends.' in their path. it undergoes some transformations before being executed. in your path. and blank. It is also used as the default when typing cd without any arguments. . HOME This is the home directory of your account. There are some common traps that can be used to crack an account which have `. Variable expansion When you give a command to the shell. the SHELL variables is usually set to /bin/sh. For example: $ echo 'hello > world' hello world SHELL This variables give the path of the shell you are currently executing. if you are executing the standard Bourne shell. PS1 The primary prompt string.The effect of this only remains as long as you are logged in. if you are missing a closing quote.. This is what the computer prints whenever it is ready to process another command. The shell prints this prompt whenever you have type an incomplete line. either at the beginning or at the end. tab. e.g.

*\).C. If you only want the first name (or only the surname) you can pipe the output through cut -d' ' -f1 (or alternatively cut -d' ' -f2.C\(. I'll fill it in as I go along. bar. and want to rename them to foo. This line will do the trick. An alternative is to install the rename script. The line that the shell sees is therefore $ ls /home/matkin Observe that no more variable expansion takes place after this initial variable expansion. As an example. The meaning is that if $HOME happend to have the value '$PS1'. etc. bar.cc. $HOME will be replaced with /home/matkin.*\)/mv & \1.gz.we start by considering one of the more fundamental transformation. . We want to prevent the shell from doing this expansion sincels might come out as ls -F (which would behave strange) or ls -l which is really bad. Renaming several files at the same time If you have a number of files named foo. -f1 Which version you use depend on what type of system you have. please mail me. if the second word is the surname). In my case.cc\2/' | sh The backslash before the ls command is to prevent is from being expanded.cc. etc. that of variable expansion (also called parameter substitution).C* | sed 's/\(.gz. \ls *. -f1 grep "^matkin:" /etc/passwd | cut -d: -f5 | cut -d. Here a lot of text is missing. Find the full name of a user If you want to find out the full name for a user name you can use one of these oneliners to do the job: ypmatch matkin passwd | cut -d: -f5 | cut -d. If you have suggestions for more one-liners. These one-liners serve both as educational examples that solves "real problems". let us assume that we have typed the following line to the shell: $ ls $HOME The shell will then see that $HOME is a variable (also called parameter) and replace it with its value. the line above would try to find a file with the name '$PS1'. in the case that is is an alias and you are using shell that has aliases (such as Bash). which is written in Perl.C. One-liners Here are some one-liners that might come in handy some time.

Remove executable files that has a corresponding C-file Assume that you have a large directory containing a lot of small C-programs together with some real applications. Note! Be very careful about what you use as expression to grep. together with rm. Here I wanted to find all executable files that matched the filename pattern *gif*.c-file but keep all other executable files.Remove processes matching some regular expression If you have a number of processes that you want to kill. or a command with wildcards in. Finding programs matching a wildcard Sometimes you want to find a program matching some wildcard. .c removed). The following line might be useful. If I want to remove all the test programs in one go I type the following line to my shell for x in *. The small files might be test programs to test details of the large program. insert an echo in front of the the rm to make sure that the command does not do anything wierd.c ] && echo $x. If your kill does not handle multiple pids' you can either use the one-liner ps xww | grep "sleep" | cut -c1-5 | xargs -i kill {} 2>/dev/null or use a for-loop: for x in `ps xww | grep "sleep" | cut -c1-5` do kill $x 2>/dev/null done But then it is not a one-liner any more. In this case I usually compile the test programs into executable code with the same name as the file it came from (with the . Note! As always when you use a complex command. do [ -x $x -a -f $x. one of the following oneliners might be useful: kill `ps xww | grep "sleep" | cut -c1-5` 2>/dev/null ps xww | grep "sleep" | cut -c1-5 | xargs kill 2>/dev/null This will kill any processes that has the word "sleep" in the calling command. You might get more processes than you wanted killed. done | xargs rm -f This will remove all executable file with a corresponding .

do for F in $D/*gif*. Generating commands for sh A useful trick is to rewrite a line into a shell command and then pipe the output into sh. echo "$first and $rest". done ) Verifying a set of e-mail addresses This scipt requires you to have some more elaborate commands. It is worth noting that the IFS is only regarded when using the readcommand or the for control structure. the following line will do the job. As an example. do [ -x $F ] && echo $F. done.se (this is the computer I use). I will try to summarize some of them here. Splitting a line using read If you want to split a line into parts you can always use the read command. you have a variable FOO containing "foo is a bar". here is a script that works almost the same way as the which command: #!/bin/sh IFS=: for p in $PATH . Assume that. Assuming that you have all your addresses in a file called mail-list and want to verify them using the SMTP daemon at kay.uu. One command that you might not have on your system is the command socket(1) written by Juergen Nickelsen. and the rest into the variable rest: echo $FOO | { read first rest . you can reset the variable IFS to split a line. } See below for a better example of when this trick is useful.docs. for some reason. Splitting a line at arbitrary characters by redefining IFS If you want to split a line into parts where the parts are separated by something else than whitespace. when we rewrite a line containing a file name into a command involving the file name. One such example can be seen above. The following code can be used to put the first word of the variable into the variable first. echo QUIT ) | socket -c kay smtp Tips & Tricks There are a few tricks that you can use when you write shell scripts. for D in $PATH.*/VRFY <&>/' mail-list . ( sed 's/.( IFS=: .

This regardless of what value MANPATH had before the call. We write the following script into the file email: #!/bin/sh IFS=@ read name address echo "A mail to $name at $address" read subject echo "Subject: $subject" The script is fed its input through standard input. This will result in the variable being set for that command only. in the same manner as you do above.uu. to show that the IFS doesn't affect the second use of read.se .uu.se Something strange @ my place EOT to a shell. Calling this script in the following manner (the > and $ are prompts) $ > > > email <<EOT matkin@docs. immediately followed by the simplecommand (don't write any . Feeding a script through standard input Sometimes you want to split a string into components.do if [ -x $p/$1 ] then echo $p/$1 return fi done echo "No $1 in your path" 1>&2 return 1 Setting a variables for one command only If you want to set a variable for one command only. Assume that you want to split an e-mail address into name and domain address. will produce the output A mail to matkin at docs. As an example. but now you want to store the components into variables. This is most useful when you have a string that you need to split at something else than whitespace. We will also supply an extra Subject line. you can always write the variable setting first. but keeping the old value (if it had one) after the command has been executed. not go through them using a for loop. if you execute the code MANPATH=/usr/man:/usr/local/man man test will only look for the manual for test in directories /usr/man and /usr/local/man. after the assignment). To do this you can feed a script (or a function) through standard input instead of supplying arguments to the script and then use the read command to set variables to the supplied values.

convert the filenames to contain uppercase letters only (this example may be a little contrived). We write two scripts that do this. The first script calls tr inside the the for-loop: #!/bin/sh for x in *. assume that you want to go through all C files of a directory and.c#' in your directory and you want to remove it you cannot remove it by typing: $ rm #foo.7 seconds. Some of them has to do with what is in this document and others require some thought and some testing. Exercies 1 If you have a file named `#foo. try to avoid putting the pipes deep down in the control structure. you will not spawn more processes than necessary.2 seconds to process 33 C files while the second takes approximately 0.c do [ -r $x ] && echo $x done | tr 'a-z' 'A-Z' On this computer (a SPARCstation 10). Remember that you are not restricted to putting a pipe after a simple command. Exercises This chapter contains some exercises. but that you can put the pipe after a for-loop. if they are readable to you.c# Why not? .c do [ -r $x ] && echo $x | tr 'a-z' 'A-Z' done and the second script calls tr outside the loop: #!/bin/sh for x in *. If you do this properly. As an example. or any other control structure. a while-loop. the first script takes approximately 6. but they do it in slightly different ways.Subject: Something strange @ my place The use of pipes When you use pipes to pass strings along.

The beer has to stand in a warm place for 7 days and after that it has to stand in a cooler place for 2 weeks. mail(1). The compiler is mounted on a computer that just went down so you can't recompile the program to print the data you want. sh(1) Hint: Look up how the << redirection works in sh(1).Exercies 2 If you have a file named `-foo' in your directory and you want to remove it it will not work if you type: $ rm -foo Following the above example you could try to type $ rm '-foo' but this will not work either. You have a tendency to loose track of such mundane things so you want to write a small script that sends you a letter after 7 days telling you to move the beer and another letter 2 weeks after that that tells you that the beer is finished. . You have a program measure that will take as argument a file name and write a line: <file> <number> <average length> on standard output. Why won't it work? How do you do to remove the file? Exercies 3 You are making a batch of beer. you'll do them yourself some time :-). Write a script that runs the programs. Exercies 4 It is 3 o'clock in the morning and you have been working on a AD2 exercise that involves a lot of measuring and other dreadful stuff (don't laugh. You are very tired and don't want to wait around for the computer to restart itself. Each run takes a very long time and you don't want to spend your time watching it. Unfortunately this is not what you want. References: at(1). Also show what command you type before you log out and leave for a good nights rest. times them and reformats the output to: <number> <user time + system time> and sorts in on increasing <number>.

echo(1) Hints: This is not an easy exercise. sh(1). In this case in the form of a manual. Let ut call the program whereare (in contrast with the program whereis which searches for a program. test(1). Examples of scripts This section gives some examples of simple scripts that might come in handy at times. $ whereare ispell spell The following command will look for a file matching the pattern foo:*. but the more interesting examples uses BASH functionality quite heavily. sort(1). .References: batch(1).txt' ENVIRONMENT PATH The path whereare uses to search for executable programs. As far as possible I avoid explicit BASH constructs. DESCRIPTION takes a list of file name pattern and looks for executable files in the path that matches the file name pattern. What we want is a generalization of the command described above. Let us instead try the following approach. we first write down the specification. $ whereare 'foo:*. calc(1). . As always when writing programs. but unfortunately it only prints the first instance of the program it finds. time(1).txt. The program which does almost this work. Finding all executable programs in your path Sometimes you want to find all programs in your path that are executable. not only the first one. SYNOPSIS whereare pattern . whereare EXAMPLES The following code will look for ispell or spell. .

} if you use the "old style" BSD shell. A short example on how to use the program. You might have to do some minor tweaking with them to make them work (changing paths.. Well. turning ${foo:?well. the script appear as follows #!/bin/sh for P in "$@". go through the path to see what matches the file name pattern. Remember that if the pattern matches one or more files. [ 17:42:56 ] @ Owein $ .} into ${foo?well.Not too complicated.) Some of them are just hacks that I wrote to do something that I needed to be ./whereare '*mail*' /export/matkin/bin/mailserver /export/matkin/bin/mailto /export/matkin/bin/mailto-hebrew /export/matkin/bin/metamail /export/matkin/bin/patch-metamail /export/matkin/bin/splitmail /usr/ucb/mail /usr/sup/misc/bin/ml. Note that we have to surround the file patterns with single quotes ' to avoid the pattern from being expanded by the shell before it is sent to the script. do for F in $D/$P.. do IFS=: for D in $PATH. Complete Scripts Here are some complete scripts. for each pattern. this will result in a list of file that matched.. do [ -x "$F" ] && echo $F done done done The outer loop will go through the supplied list of file name patterns and the inner loop will.mail /usr/openwin/bin/mailp /usr/openwin/bin/mailprint /usr/openwin/bin/mailtool /usr/bin/mail /usr/bin/mailcompat /usr/bin/mailq /usr/bin/mailstats /usr/bin/mailx /usr/bin/rmail It seems to work quite ok. etc.. The inner-inner loop is used to expand the file name pattern. We then have go through each of the files to see which of the files that were executable.

These scripts can be used as they are. garbage-count This is a program that counts the garbage in a set of accounts and produces shell code for /bin/sh that will send mail to users having more garbage than a predefined limit. It is used here to supply the manuals to the Web. measure This is a quite complex command that is written using BASH. The script makes $COUNT measurements starting at $START and increasing by $INC each step. You don't really have to know any linear algebra to use the script. Might be of interest to you too. resort the pages using psbook(1) and put two pages on each page using psnup(1). serve as inspiration. just replace the command and the functions accordingly to make least-squares approximation to other linear functions. Then number represents the size of the array to be sorted. thereby projecting A and mto a 3-dimensional space and solves the resulting linear equation. and c which we want to compute). man A script that is used to get a manual entry for some manual in CGI format. booklet This is a small program that I use when I want to print a DVI-file in booklet format. sweep A Bourne shell script that is used to remove garbage from your account. It then emits calc code to store the user time for each execution in a matrix m and stores the supplied number in the matrix t. What it does is that it assumes that there is an executable file named test_sort in the same directory and that it accepts a number as its first (and only) argument. without the constants a. hacks A collection of BASH functions and other code that I use. I give no guarantee that they are correct or even that they will work. . I wrote it to measure a sorting routine I wrote in Ada 95.done and some other are serious scripts intended for distribution. It is configured to remove all emacs backup files and all core files. b. Afterwards it generates code for a matrix A representing the function n + n * log(n) + 1 (i. The script will convert the DVI-file to PostScript using dvips(1). or as examples on ways to do things.e. Manual included (in runoff format). It then generates code to multiply A and m with the transpose of A.

..4.

99.-3 4:2.0903/90 5.

420.

93.2.

.7598 -793 !%.00704:5:94:743 8.4:/-0905..-3 .

420.

2.93.

-3!% .

483 6:490 470.0950.088.-08 %4809905.80994+ %88.42243 97.75742598973 3472.7000..9    907570/0130/....7..07/49.3/4:84:/30..34907.79.809414907570/0130/.94190804:.:939089..9419843702.3-0:80/94.84:.4:39 98..... 170880941.3094 9089.3..:7703900..7040/3 14:44:9 4:7 .:903 953.4:7419080 00704974:90247025479..-08:80/147/11070395:75480870.7989.079870.990-033347.3.3/  !$ %080.7..094./94574.9 0907.9204:43 4:.394308.074:.809 94.75742598973 3472.8089.30800.-08 %0708.7.:70.9 %070.07.425:907 57398030.33.4:39.7.42243945:9 34:75.589.79:510  49098..7:20398  !$ %0572.843..708420.7/4:73080 90$.3/.:93 0  14: .38.4 04 47/  04 47/  $ $ %8.990.990 03/ %88380.7-0 9075:75480    %8890420/70.80994+ %0805739898574259 030.//..%00110.702883.7.42509030 0  14:...890/01.422.84:80/.0905.90/9490 -0.250 0./94:9.947414:7.90.00.079204:89.0+ 39075.-08.70.43/.-088:8:.7..9.308-0:3/43083.3//08.

-3.

7.422.-4:998.0.3843 034:.10/805.4250901:7041...2470./94.3  09.9.8  %88809949039073.8099485.5503/8  ..907  '.0 9.381472.090..3/-.9478 3472.:90/ $3.3/949080 9:3/07408842097.9438-01470 -0300.7.-005.7034970.00.

.79-..09 998.3843 ..7.90 ..2039.089.84..7...0950/90144330949080 8  %0809038009.88:209.3/705.-0 05..0/5.438/073430419024701:3/.80  -0705..0/9.7.20907 .:0 32.9 8..7.250 09:8.941.381472.30.943 9.97.209078:-899:943 8.84.-0 .0/5.

420.

990 808008890701470 8.2.93 %0309.

420.

04:/979413/.929..25089.085.3/.-4.20920 14:..7   09.7 ..3/8420920 %080430 3078807.2..3994703..-0 05.7.93 -807.3:2-07411083.5503/94.0.-005.20902 94144 ..108..4203.38439. -.574-028 14:.0870.09.91 .  8  80/ 8.0 -49.7.43   30 3078 070.07.9908.19079839.20/144  -.090.802. . %830/49097.3843 %020..2380.708420430 30789.20  #03.80/:.494190982883  193..0.08:089438147 2470430 3078 50.84.9342470..943.  09.0.984.20 !$   070.109903.3389..:0 !$ 9030 .

    .

.2.  ..

.399413/4:9901:3..809.:9 /  1 705)2. 4:/-0.0894389..8..90703.03990801742/439805. 8 %0-.8799033!07  3/901:3.93.8-01470908.3:80430419080430 307894/4904- 52.30 478 .208.4204:9.-.88  .204:.9.9073./  3.0897.3/894570.39 94570..3/0/ 390 .8.935.3.384383..03981742-0305.2041.88/.8 0.870.808 8:.759 ..70:83809.0829.:9 / 1.8.988.:8073.9.20147.:807 14:.3/4:.8.422.9.2.

09.

.:9 /  1 .078434::80/0503/43.3550904:95:9974:.9.88/.0.995041889024:.5.20 4:.:9 /   1 19080.9073.3990 17893.:9 / 1.20 4743908:73.43/47/8908:73.0 14:43.20  .:9 /   1 47 ...

.:9 . +.0.0574.3:2-0741574.#024.705708843 14:.9.088082.088089.3994 43041901443430 307829-0:801: +587058005.94:.3842070:.

/0.

:9 .78. .3: 587058005.

/0.

:9 .89047/8005390..3/02:9505/8 4:.3574.422.3: %8. .9..30907:8090430 307 587058005.3.3/ 1 4:7/408349.78 <.088089.

/0.

 + /4 .3: 47:80.147 445 1473+587058005.:9 .

/0.

0.94::80.0/90103.9. 5747.47708543/3 .4250.422..:9..28949089/09.92..9.00..22.10829-090895747.07.282..7/ $42092084:.-01089.4/09908..390/0/    #024.00.841 90.088089.:9.:9.30.430 307.9.439.2 398.701:.70/70.3/ 47..7/ %0144330 29-0:801: 070.42509090895747.0.3: /430 :990398349..94:.399413/.3994 7024.705747.422.55.32470  4900.20 5..4907 00. 1 .:9.7/83 940907972 38079. 10-:9005.-0109.28940907 9842070.47708543/3 10 88:209.-4:9./.08:709..-01089.34:..99073 1  .0.80570884394705 4:2909 2470574.( 0.000.:9.8034::80.2839400.3.947.9.431743941909072942.-0108  4908.494182.7024.28343049509014433094280 1473 /4  .9438 %082.33.390/9413/.422.3//408349/4.38420/.203..201742 990 .80:8:.9 90.4/430.0/ 1.8.20..3/9 /.-0 ..9090895747.890109.39307/    3/35747..7872 1 %87024.5747..

$1473!%/41473.

0803 88:239.3/ .3/9.9.425:907 :80 90144330/4904-  80/ 8.//7088083. 1 /4 ( 0.422.-47.0842024700.90.59706:7084:94..422.3994..09  79903-:0703 .4:7.809410 2.0243.94:.422..0.8 :: 80 98890.3/8  30.071902:8390$%!/.0434:788902890.4 /430/430  '0713..0/2. 89.9 4:29349.10. /4..//708808 %88.3/84.

.

'# .

798070905.-0$94859.7..422..7.3/90708939490.3:80034:790808.39085.4/0./.9.-039490.70.9 90$84370.70805.0 03070790.9:70 8 ..-.390103.25041039897.3/  88:209..7984:.7-97.8:801:  $5993.41789.439. 890.30.7.422.8 %070..0.33.8:809070.7.3/.422..30394..798..-01789  .7599./.30.2489908..7.30 9847934939.0.70842041902070  0307.3/ .93.-099070.250.30:8370.843 4:...8.331448.89470790.90/-842093080 9..20394.94:.7.7598 9794 8:22.9 147842070..80.89.303945.8295  %58 %7.3994859.7.30.250 0708./178970890.3/81478 :801:97.1097.-0 ..7 %0 1443.439.9478.3/7089< $00-04147./ 14:...-4..0 4:.3/4790147.7/0/03:839070.3/3. 2.422.7.20.422.4"&% 84.3-0:80/945:990178947/4190..3.3-08003.3/903550904:95:9 3948  308:.303945.-07089 0..422.9078-70/0133$ 14:.20  $5993.43974897:..890.09 .3994859.37080990.4.10 3.4 70.

-3.

8 $ 14753!% .

/4 1 5.

45.( 903 0.

4434:75.422..901440/-908250.3/43 14:.422..879090..:90/ 8..9.422.190790.3/43 4:.422.7..3 0.-0147430.422....3994809.-0 809931789 220/.8832039 %8708:9390.:9090.7.250 14:00.-08147430.3/ /43 9790./430 .7..3/43 -:9 0053904/.:0 19.8-00300.7. 709:73 1 /430 0.3.3/.4/0 !%.-0-038091479.3.9  709:73 $0993.190790 .

:87.

2.3.

:87.

..4.

32.94708.14790893/70.2.39089 4344147902.3:.

:87.

3/.2.3.

:87.

..4.

.8.3097.99080.30 2../-0147090.7.759. ..9.3100/..$:-0.0  88:209.1:3.9 4:300/94859.8973394.7/ 35:93890..3/94 809.0.7:2039894908.3307.2..:0!%..-08 3494974: 902:83./ 07909014438.3.//70883943.//7088 0 .8.3/903:809070.3/.759974:89.  00/3.147445 %4/4984:.110.:08 %882489:801:034:..43/ :804170.425430398 3908.3//42.-4..94:.943 974:89.7/35:9 $42092084:.3994859.425430398394.98420930809.202.3994859.0 -:9344:./.3/.422.89739.7/08841.930 94849.7.3  %870.990$/4083 9.20.39948947090./418:553.759394901002.39085.-0894908:550/.84: /4.759 47.848:55.

-3.

20.3025.98:-0.93/4.9./3./8:-0.//7088 0.0904:95:9 2.8 :: 80 $42093897.//7088 70.3/.942.0  % 94.9 %08.705742598  02.80 574/:.3988.20.7/35:9 .7593901443 2.943.42.3/.3307 90.4$:-0.9/4.93..759810/9835:9974:89.8 $70.9 0. % 2.8 :: 80 .

990.9:70 14:/498574507 4:34985.4397.7070.422...3/ 1 90.0 445 47.4/5:993905508/005/433 90..8  %017898.330.147 445 .35:990550./70..9$42093897.9/498 -:990/493 89/1107039.3/ -:99..759.43974897:.2502. 8250.-0.10841.8889738./.439.7  8.3025.947.1907.0/ 0790948.94:.20894.250.9:70 #0202-079.88:209.43974897:.94:.32470574.088.89738/09090147 445 .-0944: .94:.75989.3 4907.1907.07990103.$:-0.39944974:.7034970897.8009907843 98 0.3:5507.43 9794.0 %0:80415508 034::805508945.30.43.08808 9.550.90/945:993.

-3.

 /4  7( 0.497 .      /430 ..8 1473 .8974:98/090445 .43/8.759.3/9080.

-3.

 34:7/70.55742.947. 349 .3/49078706:70842094:9.55742..808 $42041902.425:907 .388420007.094: .20/+144 .39947024.3/842090893  07.894/49.808 %8.:2039.09-953 72144 .4 /43097 .98398 /4.439.08.08810809080.7599.$!#89.43/9. /4  7( 0.90 80..08.43/8   07.3/4:.      398.103.43/894574.5907.90  80.08 14:.943 9017898..0.8 1473 .33497024.

3.: 4: /4902 4:78018420920 4:.44/3987089  ..990-00781380/  #010703.3/4:.3/4907/70./1:89:11 /43 9.0.809.3/4:/43 9 .7/4:95:9 &31479:3.0147008 4:.0147.0039 4389.7:2039.30938844:.494120.3994790.9.8.97:38905747.98904:95:994 3:2-07:807920 88902920 .  8   3944:549070/70.903/03.5747.07.89489.39947024.9:89039/43844:.725.7:39.8..39948503/4:7920.0147/.-4.82.44075.425:9079.3/3.220.0743920.89489.3/4:.74:3/14790.4250 905747.3/0.418:.090-007.3/..08 984 .3 970.42507824:390/43.08...20/+ 144 34:7/70.94347838   07.-.39 790.90988349.3/.833:2-07 8484.4:..7599..99.294573990/.3//43 9.7599.9 3.3490709907008.9.8..19079.1907/.20.3/790.10 3.41-007 %0-007.0-00347343.39024733.425:907947089.9803/84:.9  2.3/701472.08 14:.89034:9424.3/3.70.8:73.0..9 .30 103:2-07.4.70.007.422.19079.9 9.947..08..9.08 4:.8:709.8.099349 4714:950 72 144 44390.99084:9. 09907.0..3/847983433..28 9208902 .4:/9794950 72 144  -:998349470907  43 9947 4/44:/4947024.39  %0.3994..2504:.103.2:3/.702.3/4:950-014704: 44:9.09010 07.94:.07970/.08.07.3/ ..0.944480 97.99.39 4:.799801 .00.9.4.

899905747.422.399413/.99073144 070.30.4/05.943.2834:75.  3/3.705.99208  81.08-.0890103.3/44147..28 01789790/4390850.  920  .  8  8479  9089  0.3/44814700.80390147241.99.8941103..-4.2508 :808$1:3.4203.99073.929..70 144 99  '# % !% %05.9$.08.2913/8 .-01083905.24899847 -:9:31479:3.7-0/.9070.905747./97901443.9..4/04414785047850  99  %01443.398.2070.14700.:9.0  09:83890.4   398%88349.9.3905.94341 90.9.5747.80.70 3 .5574.43897:.709.  $ !$$ 070.20708.#010703..7.3/.943.3.98 -:9902470390708930.25084182508..041905747.96:900.2 8.5747.-05747.7.9 $42092084:.99073  !$ 070.2834:75.28  .7598 %880.205..9 2..:9.7.8007.00.3//08.-0 34943 901789430 %05747.4397./408.99073    $#!%  070.75989.9.:9.08147.:9.0884200.7000.102. 09:9.2508418..90943 57398901789389.803 7935747.943 398.80   .0307..70:8089480.85488-0. 2.70850850 %01443.422.-05747.99.2.1.3:.205.90.

550.90/ 0 908.81448 .759.7.49944.425..

-3.

8  147!3/4 $ 1473!%/4 1473.

2 4909.8941109.-0  84790.0/  0903.04974:0..41901089.9.99073898306:4908 94.9.3/903307 445 1470.759  ( 03 .990732.9070 00.0890103.994800.92.5.!/4  ( 0..90.990738.205.9 1905.3/90103.:9.20 5...99073 4974:905.4/905.4 /430 /430 /430 %04:9074454974:908:550/8941103.990731742-0305.9.92..205.25043494:80905747.99073 %03307 33074458:80/9405.419010894800.0948:774:3/9010 5.3/0/-9080 -0147098803994908.08430472470108 98708:93.99073 #0202-079.

70 .070.

05479.

2.93.

-3.

07 .2.807.

05479.

2.93.

-3.

2.94 .

05479.

93.2.

-3.

94 0-70 .2.

05479.

93.2.

-3.

 .209.2.

05479.

2.93.

-3.

2. . 209.5.9.

05479.

93.2.

-3.

 .8592.

:87.

:.-.

2. .

:87.

8:5.

28.

-3.

2 2. .

:87.

45033.

-3.

5 .2.

:87.

45033.

-3.

5739 .2.

:87.

45033.

-3.

2.944 .

:87.

-3.

 .2.

:87.

-3.

.9 .425.2.

:87.

-3.

2.6 .

:87.

-3.

2.89.98 .

:87.

-3.

 .2.

:87.

-3.

094/48420234790...4250908.335. $42041902. 2.090247 .  98002894476:904   425090$.7598 070..708420.7598 4:29.39 902942.9749094/48420939.70:89.9300/0/94-0 .98  9:7331440 <3941440 <14::80904/890$80  09.89.72.

8 ..3 8.990.3-0 :80/.9  2.29.894900-  .9:80 9-0413907089 944:944  .890.3:.9470.3/4907.3:.5747.83857.7.0.31472.4/0147..017424:7.02.9438.470108 ./430.039714784202.0. 3.039.08 80.98:80/947024.99047  8005 4:730808..3/84204907.431:70/947024..39009.0.94341$1:3.3/.7-.4:39890.75983903/0/147/897-:943 %0808.894/4938 .98:80/9409.4:39 %88.4:39 98 ..8-.80941.40.70..7599.034 :.70 807.250843.:/0/ 37:34111472.2.4770.0 .7599.943 47.9.4:398.7-..80.708074:88..9 98 :80/070948:55902.03.3/574/:.7598.3:.4/09.7-.3:..:5108.

-3.

.3/84.94-084790/  %08.7592.0-7..20/70.759:83/.83 -0.759..972.88:2089.5. .422..3:2-07.99.85.94394490730.422..00.4/0948947090:8079201470.3/.55742.8479374:93074903/..8981789 . 00.3/894708908:550/3:2-073902.4/0942:95.08430.6:90.9879903:83$ 7490994 20.29.908.71:3.9438.3.3/3.3/299097..908..990708.-010 3..9433 3  4 3    0 94:990..3/294.09434.8905 99030298.08:8358-44  .89 86:.39945739.47/3942..3994.8:70.0890708:9330.08 &%20.0.3/43 .' 103-4409 1472.70.4250..9$%#%.58  708479 905.4389.0598.943  4:/43 970.:9433.330.3/5:9945.38548041 9070- 5740.2.793.8:702039889.9438  .94:8078.759 :89705.3/9.5747.  .77.7:2039 %033:2-07705708039890804190.99/40889.0:83583:5   20.3/9.9:8003.93.09.708 .3/901:3.977057080393901:3.. /203843.7/890307.07990' 1094!489$.947.43..7.300. 570/0130/29  -4409 %88.99.0 90.8:70 %88.4/0147.32470..:9.82.7-..9 %08.2.0.398.7 06:.979  1907.425:90 9 9030307.3/.9803/2.89..20/9089*84793908.94:80908.