|sections in this module||City College of San Francisco - CS160B
Unix/Linux Shell Scripting
You are writing a shell script that has this synopsis:
This means that myss requires two arguments. The first is an option, which must be either -a or -b. The second is a file. We will make the further restriction that the file argument must be a readable file.
Write code for this shell script to check its arguments. Your code should output an error if the arguments are invalid.
What is wrong with the following command:
How about this one:
Can you rewrite the command so that it works correctly and is as simple as possible?
Rewrite the following command using an if statement
Rewrite the following if statement using && and/or ||
The date command outputs
Mon Jan 25 12:23:11 PST 2010
where the month is expressed using its first three characters. Write a sequence of code including a case statement that translates today's date into the format MM/DD/YYYY. For example, the date above would be output as 01/25/2010 For extra practice, you should allow the name of the month to be expressed either as it appears in the date (with the first character capitalized) or with the first character lowercase, e.g., as Jan or jan
What is the problem with the following command?
There are four bugs in this sequence: two will cause syntax errors immediately, and two are data-dependent. Can you find them? (Hint: they are all due to spacing or quoting.)
Note: the code for myss can be found in the examples-shotts/conditionals directory beneath our
class data area on hills.
First, let's discuss an algorithm for our argument checking. This is very important to do before you write the code. Here is an outline for processing arguments in general. We will ask a series of questions. At each step if it doesn't make sense to continue we will exit with an error message.
are the number of arguments correct?
is each option valid? do they make sense together? are required options present?
after the options are processed, are the path arguments acceptible?
If your program passed all these tests, you are ready to start the real work.
For our simple shell script, here is how our tests would proceed:
When we exit with an error, we will output a synopsis to help the user run our shell script next time. In Assignment Two you are given a function called fatal, which you can call to output an error message and exit. We will use a modified version of fatal in our code. (Note that this function outputs its error message to standard error. We will learn about this in the next module.
Let's look at the following command:
This is a mess, but is a common mistake. Beginning shell programmers think that [ ] is punctuation that makes an if statement work (just like parenthesis would be in a C/C++/Java expression). [ ] is NOT punctuation. It is the test command in disguise. Let's rewrite the if statement replacing [ ] with the command test:
if test grep "$user" file1 ; then ...
Most people would agree this looks silly. Indeed, the command we want to use as the condition for the if statement is grep, not test. Just delete the test command (or the [ ] ):
There is still a problem, however. The grep command, if it succeeds, will output the lines that match. You must tell grep to 'shut up'. (Many of us want to tell grep just this from time to time.) Just redirect its output somewhere so you don't see it. We will use a temporary file, then delete it. (In the next module we will use the null device instead):
The next command
is similarly over-complex. The command-substitution is not only silly, it causes a big problem. Remember, command-substitution substitutes the standard output of the substituted command back onto the commandline of the enclosing command. Suppose $user was Greg and our grep command output the following text:
Greg Boyd teacher cs160b
After the command-substitution was finished, the if statement would look like this:
Now we see how silly it is. The if statement will try to run the command Greg, giving it the arguments Boyd teacher cs160b ! (Although there should always be a command Greg, there probably isn't, so this if statement will fail.) Just remove the command substitution and redirect the output of grep as in our original solution.
Some cs160b students try to force the command-substitution version to work like this:
Interestingly, this works! However, this is due to the default option in the test command, which is -n. The command is thus:
which says, in effect, "if grep outputs any text", then ...
Although it works, it is again unnecessarily complex. If you see this type of code in a shell script, either the programmer was doing something very tricky, or they just didn't know what they were doing!
The if statement that is normally thought to be equivalent to
This is usually fine, but it is inexact. (See the closing paragraph about && / || )
The && and/or || statement that is equivalent to
grep "Greg" "$file" || echo "Greg was not in $file"
Notice how the ! changed the && to ||
Of course, most of the output we want is already in the output of date:
Mon Jan 25 12:23:11 PST 2010
The month, however, must be translated. This is where a case statement will come in handy. Let's start by using our set -- trick to place the day in $3, the year in $6 and the month in $2. Then, the case statement. Last, output the result:
|Prev|| This page was made entirely with free software on Linux:
Kompozer and LibreOffice