Solutions to the exercises done in class on Wednesday, September 22, 2004 1. Here's a solution to exercise 1. % cat divides #!/bin/csh set nums = ( $argv ) set i = 1 while ( $i <= $#nums ) @ remainder = $nums[$i] % $nums[1] if ( $remainder == 0 ) echo $nums[$i] @ i ++ end % divides 3 5 9 17 21 3 9 21 2. Here's a solution to exercise 2. #!/bin/csh set directory = $argv[1] chdir $directory if ( ! -e images ) mkdir images foreach file ( `ls *.gif *.jpg` ) cp $file images/$file end 3. Here's a solution to exercise 3 that uses a 'while' loop as specified in the instructions. This solution uses a couple of temporary files to store the intermediate results. Shell scripts often use temporary files in this way. Here I chose to use the system /tmp/ directory though I could have just as easily used the current working directory in which the script is being executed. What are the advantages of using the /tmp/ directory? You avoid the possibility of inadvertently writing over any existing files in the current working directory that just happen to have the same name as the temporary files being used by the script. You won't be allowed to write over someone else's files in the /tmp/ directory (if you try the script will probably terminate with an error) but you might write over your own files. An alternative solution would be to generate a file name that is guaranteed not to exist in the directory you want to store the file. How would you do this? Here's the solution using the /tmp/ directory: #!/bin/csh set file = $argv[1] set fix = `cat $argv[2]` set one = /tmp/$file.one set two = /tmp/$file.two cat $file > $one set i = 1 while ( $i < $#fix ) @ j = $i + 1 eval "cat $one | sed 's/$fix[$i]/$fix[$j]/g'" > $two mv -f $two $one @ i = $i + 2 end cat $one rm -f $one $two Here's a solution that relies entirely on the 'sed' utility by making use of the ability that 'sed' has to execute a sequence of 'sed' instructions in a separate file. This solution does, however, rely on rewriting the file of spelling corrections as a sequence of 'sed' instructions; this can be done with a simple 'awk' script. The 'awk' utility is particularly good for separating lines into fields and then stitching them back together using print statements: % cat mspl.txt | awk '{print "s/" $1 "/" $2 "/g"}' > mspl.sed % cat mspl.sed s/tey/the/g s/teh/the/g s/arguement/argument/g s/lawer/lawyer/g s/plaintif/plaintiff/g With the commands in mspl.sed it is now easy to complete the exercise: % cat msg.txt teh lawyer's arguement was pretty weak but tey plaintif still got a big settlement % cat msg.txt | sed -f mspl.sed the lawyer's argument was pretty weak but the plaintiff still got a big settlement You can use the above technique to strip out HTML tags from a web page or remove uninteresting material from a mail message. Think about how you might use it as a SPAM filter.