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

Examples

This section contains examples of Scripting Basics 2. 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.

1. 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?

2. 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?

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

4. Write several echo commands to output the following text exactly: 

She said, "It's over! And you owe me $1000."

5. Given the output of the id command below, write a command to extract the default group id (the integer after gid=) for the user $user and place it in the variable gid. In the example below, if $user is gboyd, your command would set gid to 208.

$ id gboyd
uid=3496(gboyd) gid=208(cisdept)

6. You have the following shell script, args:

#!/bin/bash
shift
echo "num=$#, first='$1'"

If the current directory has the following files:

$ ls -1
args
file1
one file
onery

and you have the following variable defined:

$echo "$Name"
Ka Yiu Lui

Consider the following runs of args. For each, write the output of the shell script

./args o*./args $Name./args $(ls o*)./args "$Name"
    

7. Given the variable salary, which contains a monthly salary in dollars, output a message like

You earn $XXX.00 per month.

where XXX is the value of $salary.

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

1. 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

2. 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): "

3. 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.)

4. 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 "She said, \"It's over! And you owe me \$1000.\""

echo 'She said, "It'\''s over! And you owe me $1000."'

echo She said, \"It\'s over! And you owe me \$1000.\"

Let's make it a little more complicated by placing the dollar amount in a variable $amt. Here are some possibilities:

echo "She said, \"It's over! And you owe me \$$amt.\""

echo 'She said, "It'\''s over! And you owe me $'$amt.\"

echo She said, \"It\'s over! And you owe me \$$amt.\"

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.

5. The simple solution here would be to use two cut commands:

gid=$(id $user | cut -d= -f3 | cut -d'(' -f1) 

6. Again, type in the shell script and try the examples. Here are some notes to make sense of the results:

$(ls o*)

 one file  onery

7. Again, this is a quoting problem. It is actually very simple if you used double-quotes:

echo "You earn \$$salary.00 per month"

It would be clearer using curly-braces, but the result is the same:

echo "You earn \$${salary}.00 per month"

8. The resulting shell script mystat is in this module's directory beneath examples 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 Openoffice.org    
Next

Copyright 2010 Greg Boyd - All Rights Reserved.

Document made with Kompozer