Read example scripts

Versions of read scripts

read1:
#!/bin/bash

read line
echo "$line"

This script contains a read from standard in followed by and echo to standard out.

Demonstration

$ head -1 goodfile newfile
==> goodfile <==
1 1.8
head: cannot open `newfile' for reading: No such file or directory
$ ./read1 <goodfile
1 1.8
$ ./read1 >newfile
 1 2.2
$ head -1 newfile
1 2.2

After checking the first line of the files "goodfile" and "newfile", this demonstration executes script by reading from goodfile and writing to the terminal, and reading from the terminal and writing to the new file newfile. Notice the leading spaces in the input do not apear in output.

Notes

read command
The read shell command will reads words or tokens from standard in. Words are separated by a whitespace and the read is terminated by a new line character. Whitespace is one or more spaces or tabs. The words are stored in the shell variables on the read command. If there are more words than variables then all the remaining words, including all whitespace, will be stored in the last token. A Backslash character \ may be used to remove any special meaning to the following character, this is called backslash quoting. There are three types of special characters for the read command:
  1. A backslash followed by a space or tab will put the space or tab in the word, and not terminate the word.
  2. A backslash followed by a new line will cause the read to continue on the next line, and not terminate the read.
  3. A backslash followed by another backslash will put the backslash in the word, and not quote the next character.
Head command
The head command will print the first few lines of a file. With the option head -1 the command just prints the first line.
read2:
#!/bin/bash

read -r x y etc
echo "$x, $y"

This script will read the first two words of a line and echo them with as a comma separated pair. Any additional data on the line will be ignored.

Demonstration

$ ./read2 <goodfile
1, 1.8
$ echo 1 2 3 | ./read2 >file
$ cat file
1, 2

This demonstrates executing script in the current working directory with the same goodfile as above. The first command echos the first line with commas separating the number, and the second uses the echo command to show the extra 3 is ignored.

Notes

backslash quoting
A Backslash character \ may be used in read input to remove any special meaning to the following character, this is called backslash quoting. There are three types of special characters for the read command:
  1. A backslash followed by a space or tab will put the space or tab in the word, and not terminate the word.
  2. A backslash followed by a new line will cause the read to continue on the next line, and not terminate the read.
  3. A backslash followed by another backslash will put the backslash in the word, and not quote the next character.
So this is the only inclue white space in a token, and it gives a way to combine two physical line into one logical line. When you are reading from a data file, it is unlikely to use backslashes in this way, so it is better to disable backslash quoting with -r option on the read command.
Shell Variable names
Variable names should be descriptive and not shell keywords, such as "function". Compound names can be used to avoid keywords. Here we illustrated two common ways to make compound names more readable.
  • Upper case to introduce a new word.
  • Underscore to separated words (You can not have a space in a variable name)
You can usually get away with using bash keywords as variables names, but you confuse the parser and get some hard to understand error messages.
Pipes
The character | sets up a pipe between two processes. In this demonstration the stdout of the ./echo2 command is piped to the stdin of the wc -l command. This illustrates a common use of pipes - to avoid needing to write and then read an intermediate file.
read3:
#!/bin/bash

read -r x y etc
if [ -n "$etc" ]; then
  echo "line too long" >&2
elif [ -z "$y" ]; then
  echo "line too short" >&2
fi
echo $x${y:+, }$y

This script has two echo commands with one argument in double quotes. The first is conditional on the variable figTitle containing data. They are both preceded by a source command. The file on the source command will contain variable assignment statements for variables needed to construct the 3 or 4 gnuplot commands.

Demonstration

$ ./read3 $ ./read3
1
line too short
1
$ echo 1 | ./read3 >file
line too short
$ cat file
1
$ echo 1 2 3 | ./read3 >file
line too long
$ cat file
1, 2

This demonstrates executing script in the current working directory with output to the terminal window. The error message is because there is no file to source, and following output shows the results of undefined variables. They are interpreted as nulls (0 length strings). There are example files which can be used as a run control file. The two commands cat commands will copy an example file to the .echorc file and display to contents. This way you can see the run control file and the resulting output.

Notes

Sourcing a file
The assignment statements can now be in the file .echorc. By sourcing the file these variable assignments, and will be available to the original shell. The statements in a source file are executed in the same environment as the original shell.
if... fi structure
The if test command begins an if/then structure, that is terminated by the fi command. The then is a separate command, and if it is on the same line you must separate the commands with a ; character. Spaces are important to make sure the commands a properly recognized by the parser.
Test for empty string
The test [ -z "$myvar" ] evaluates as true if the myvar has zero length or is undefined.
The test [ -n "$myvar" ] evaluates as true if the string is defined with content. The -n is optional, so just a variable in double quote is a test for a string with data.
cat filename
The cat command will read from standard in write each line to standard out. When the output is redirected to a file this is just like the cp command. However, the cat command is more general. It can write to file, the terminal or to a pipe.
echo4:
#!/bin/bash

[ -r .echorc ] && source .echorc

case "$imageFile" in
  *.png )
     echo -n "\
set terminal png transparent size $imageWidth,$imageHeight
set output \"$imageFile\"
"
      ;;
 *.svg)
     echo -n "\
set terminal svg size $imageWidth $imageHeight dynamic
set output \"$imageFile\"
"
esac

echo -n "\
plot \"$dataFile\" with points pointtype 6${function_x:+, }$function_x
"

The source command is the second part of the compound command:

test command && source command

The test command [ -r .echorc ] evaluates as true if the file .echorc is readable. The source .echorc is executed only as needed to determine the truth value of the compound statement. This script has two echo commands with one argument in double quotes. The first is conditional on one of two cases that depend on the pattern of the string in variable imageFile. The second echo uses the alternate value expansion ${function_x:+, }. This expands to ", " if the variable function_x has data and null otherwise. This way there will be no dangling comma when the function is not supplied, or is null.

Demonstration

Example using expand to expand the tabs
$ ./echo4
plot "" with points pointtype 6
$ cat figrc | tee .echorc
imageWidth=500
imageHeight=400
imageFile='fig.png'
dataFile='fig.data'
$ ./echo4
set terminal png transparent size 500,400
set output "fig.png"
plot "fig.data" with points pointtype 6
$ cat fig1rc | tee .echorc
imageWidth=500
imageHeight=400
imageFile='fig1.svg'
dataFile='fig1.data'
commandFile='fig1commands'
function_x='0.83*2.046**x'
figTitle='Data with fitted exponential'
$ ./echo4
set terminal svg size 500 400 dynamic
set output "fig1.svg"
plot "fig1.data" with points pointtype 6, 0.83*2.046**x

The first example in figrc is written based on the *.png pattern of the imageFile. Notice that there is no dangling comma on the plot command. The second example in fig1rc is written based on the *.svg case. Notice that for format of the commands are slightly different.

Notes

tee filename
The tee command will pipe everything for standard in to standart out and copy the lines to the file on the command. In this case we using it so the line being stored in the .echorc file.
Lazy evaluation of && and || compound commands
With lazy && evaluation, the second command is skipped if the first fails. (If the first fails the the compound command and fails and there is not need to evaluate the second.) This a convient way to do one-line if statement. With lazy || evaluation, the second command is skipped if the first evaluates as true. (If the first is true the the compound command and true and there is not need to evaluate the second.) This a convient way to do one-line unless statement.
case... esac structure
The case string command begins an case structure, that is terminated by the esac command. The ( pattern begins the individual cases. The commands up to the ;; are executed if the string matches the pattern.
Alternate and default values parameter expansion
The parameter ${myvar:-foo bar expands as $myvar if there is data in it's value( not empty), or to "foo bar" otherwise. The string after the ":-" is the default value.
The parameter ${myvar:+foo bar expands as an empty string if there is data in it's value( not empty), or too "foo bar" otherwise. The string after the ":-" is the alternate value.
IT Help Center
University of Delaware
Last updated: August 11, 2010
Copyright © 2010 University of Delaware