sections in this module City College of San Francisco - CS160B
Unix/Linux Shell Scripting
Module: Shell Basics
module list

Examples

This section contains examples of Shell Basics. Most of the answers are at the end of the section, with some comments. Some of them require you to actually test the solutions on your own. These examples are not meant to replace the Exercises. Do the exercise sets!

Some of the exercises have sample files. The sample files are on hills in a subdirectory beneath /pub/cs/gboyd/cs160b/examples-shotts. The sample files for this set of examples would be in the subdirectory named basics.

1. Given two integers xxx and yyy, write a command to 

a. output their difference
b. set the variable sum to their sum

2. Which of the following variable names are illegal?

4runnum.bernum_ber_4runcomma,s
typ4metypOverylongvariablenameALLCAPStechno-crat

3. Alexi found the following line in the beginning of a shell script:

TESTDIR=${TESTDIR:-$PWD}

Explain to him what it means.

4. What does the following command sequence do? 

string="Henry"
num=$(grep -c "$string" "$file")
echo "There are $num ${string}s in '$file'"
  1. Why are the curly-braces required around string in the echo command?
  2. Why does $file have double-quotes around it in the grep command?

5. Li wants his prompt to double as a clock. He sets his prompt like this: 

PS1="$(date): " 

However, when he types enter, the date in the prompt doesn't change. What is the problem and how can he fix it?

6. You have two files, file1 and file2. Write a command to output how many more lines file1 has than file2

7. It was a messy breakup and Susan is writing a 'dear John' letter in a shell script. (ok, you have to smile at that one.) She figures he owes her some money, so she's adding that into her message. If the amount owed is in a variable $owed, write an echo statement that will output the following text exactly:

I say, "It's over! and you owe me $XXX"

where XXX is the value of $owed

8. Write a shell script mystat that outputs the following information:

formatted as follows:

Welcome to HOST. It is MON DAY YEAR at HH:MM.
The system has been up for HOWLONG. There are N users.

You may want to look at the output of the following commands to extract your data:



You should answer (and explain) the questions above before looking at the solutions below!

Solutions

1a. There are several ways to do this:

1b. Either

2. 4run num.ber comma,s and techo-crat  are illegal. A variable name may include letters, numbers and underscores, but it cannot start with a number.

3. The shell script is ensuring that the variable TESTDIR has a value. If it was set and exported, the shell script will use the value. If it was not set (or not exported), the shell script will set TESTDIR to the current directory. Note that, in this case the syntax TESTDIR=${TESTDIR:=$PWD} is no different.

4. It outputs how many lines in $file contain at least one instance of Henry.

  1. The curly braces indicate the variable's name is string. The suffix s is appended to the contents of the variable. If the curly braces had been omitted, the name of the variable would have been strings.
  2. The double-quotes ensure that the file's name is the entire contents of the variable file. If $file had multiple words and it was not 'held together' with double-quotes, the file's name would just be the first word. It is very important on modern systems to always use double-quotes around a variable that contains a file path.
This problem can be seen like this:
file="my file"
cat "$file"  is the same as  cat "my file"
cat $file  is the same as  cat my file

5. The problem is when the date command is run. When $(date) is in double-quotes, it is run and the result assigned to PS1. This is what you normally want when you are using command-substitution. This results in a constant date being assigned to PS1. In the case of prompt strings, however, they are re-evaluated each time the prompt is output. Thus, if PS1 has the string $(date) in it when the prompt is printed, the date command is rerun each time the prompt is printed, which is what you want. You can see this in the following two examples. The first evaluates the date when PS1 is assigned. The second evaluates it whenever the prompt is output.

$ PS1="$(date) "; set | grep "^PS1"
PS1='Sat Apr  3 14:40:39 PDT 2010 '
Sat Apr  3 14:42:41 PDT 2010  # these are instances of the new [ugly] prompt
Sat Apr  3 14:42:41 PDT 2010

$ PS1='$(date) '; set | grep "^PS1"
PS1='$(date) '
Sat Apr  3 14:42:13 PDT 2010  # these are instances of the new [ugly] prompt
Sat Apr  3 14:42:15 PDT 2010

You could alternately escape the $ in the command-substitution when you assign to PS1:

PS1="\$(date): "

6. echo "$((  $(wc -l < file1) - $(wc -l < file2) ))"

(This is command-substitution embedded inside arithmetic substitution. The extra spaces between the $(( and the $( are not required, but are there for clarity. Of course, if file2 has more lines than file1, the result will be a negative number.)

7. This is all about using quotes correctly, and is difficult as you have a mixture of single- and double- quotes in the output. Here are some suggestions:

echo "I say, \"It's over! And you owe me \$$owed.\""

echo 'I say, "It'\''s over! And you owe me '$owed.'"'

echo I say, \"It\'s over! And you owe me \$$owed.\"

Although it is not apparent here, the real problem in this sequence can be the exclamation point(!). If an exclamation point is a prefix to any text, it is interpreted as a history substitution. The only way to disable this is to use single-quotes. In our example, we are safe, since the exclamation point was followed by a space.

8. The resulting shell script mystat is in this module's directory beneath examples-shotts/basics on our public work area on hills. A copy is below:

$ pwd
/pub/cs/gboyd/cs160b/examples/3-basics2
$ cat mystat
#!/bin/bash
#
# this shell script outputs the following information
#   - the host it is being run on, and the date and time run.
#   - how long the system has been up
#   - how many users there currently are
#
h=$(hostname)
#
# break apart the date using set --
# the date command outputs this syntax:
#       Sat Apr  3 15:15:29 PDT 2010
#
set -- $(date)
date="$2 $3 $6"
time=$(echo "$4" | cut -d: -f1-2)
#
# the uptime command outputs this format:
#       3:17pm  up 94 days, 21:37,  6 users,  load average: 0.05, 0.06, 0.06
# we will just output the days up, and we'll use sed to capture it
# the following command captures the longest sequence of text that does not
# contain a comma after the string 'up ', then just substitutes what it
# captured for the entire line.
#
up=$(uptime | sed 's/.*up \([^,]*\).*/\1/')
#
nusers=$(who | wc -l)
#
# now we're ready to output the results:
echo "Welcome to $h. It is $date at $time."
echo "The system has been up for $up. There are $nusers users."

Prev This page was made entirely with free software on Linux:  
Kompozer
and LibreOffice.org    
Next

Copyright 2016 Greg Boyd - All Rights Reserved.

Document made with Kompozer