CHAPTER 27
Read Piped Input

Many programs available to the UNIX or Linux operating systems have the ability to process input from standard input through a pipe, Similarly, the following short script demonstrates how to perform this task using a shell script. The script also demonstrates a number of interesting techniques that are covered in more depth elsewhere in this book.

The purpose of the script is to take its input, whether from a file or stdin, and print the data to stdout in reverse order. The script provides two ways to perform this task. The first method works by calling the script with an argument that is the name of the file to be reversed. Alternatively, you can pipe output from some other command into the script, and it will then perform the reversal on its standard input.

First we initialize a counter variable that will track the lines of input the script receives.

#!/bin/sh
counter=0

Next we define the populate() function.

populate () {
  counter=$(($counter+1))
  eval COUNT${counter}='$LINE'
}

This function creates a new variable by calling the eval command. The eval command performs variable and metacharacter expansion in what follows before passing the result to the shell to evaluate; it is used here to construct a line of code (an assignment statement) out of the contents of preexisting variables. This is a fairly powerful method for creating command lines at runtime and is explained in more detail in Chapter 7.

The populate() function first increments the counter variable and then creates a variable called COUNTnn where nn is the value of the counter that in this case refers to the specific line of input to be reversed. The collection of these variables behaves analogously to an array, except that the limit on the number of elements is based on the amount of memory the shell makes available rather than the preset limit for the shell's array construct.1

__________

1. The maximum number of elements in an array in ksh88 is 1024. In ksh93, it is increased to 4096. bash has no range limit.

Now we check to see whether a filename has been passed to the script.

if [ "$1" != "" ]
then
  if [ -f $1 ]
  then
    while read LINE
    do
      populate
    done < $1
  else
    echo "$1 Does not exist, please try again"
  fi

If it has, the script tests whether the file exists. If the file is validated, the script redirects it into the back end of the while loop. This loop calls the populate function for each line of the file. If the file named in the command line doesn't exist, we just output a simple error message.

You may think performing a cat of the file and piping the result into the front of the while loop would work, but this can have unforeseen results. It works in ksh without a hitch, but not in pdksh or in bash. (For more information about piping data into a while loop, see Chapter 10.) Redirecting the file into the back end of the while loop always works.

If no filename was passed to the script from the command line, we assume the data is being piped into the script.

else
  while read LINE
  do
    populate
  done
fi

Each line is read in sequence, and the populate function is called to expand the variables to their values.

Once the script has finished processing all the data, the counter variable contains the number of the last line of data that was processed.

while [ $counter -gt 0 ]
do
  eval echo '$COUNT'$counter
  counter=$(($counter-1))
done

This while loop then counts down from the counter value, decrementing by one each time, outputting the contents of each of the newly created variables. Thus we reverse the order of the lines from the input.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.22.26