All programs and scripts require input in order to be useful.
Inputs commonly include things like scalar parameters to use in equations and the names of files containing more extensive data such as a matrix or a database.
All too often, inexperienced programmers provide what should be input to a program by hard-coding values and file names into their programs and scripts:
#!/bin/csh # Hard-coded values 1000 and output.txt calcpi 1000 > output.txt
Many programmers will then make another copy of the program or script with different constants or file names in order to do a different run. The problem with this approach should be obvious. It creates a mess of many nearly identical programs or scripts, all of which have to be maintained together. If a bug is found in one of them, then all of them have to be checked and corrected for the same error.
A better approach is to take these values as input:
#!/bin/csh printf "How many iterations? " set iterations = "$<" printf "Output file? " set output_file = "$<" calcpi $iterations > $output_file
If you don't want to type in the values every time you run the script, you can put them in a separate input file, such as "input-1000.txt" and use redirection:
shell-prompt: cat input-1000.txt 1000 output-1000.txt shell-prompt: calcpi-script < input-1000.txt
This way, if you have 50 different inputs to try, you have 50 input files and only one script to maintain instead of 50 scripts.
Another approach is to design the script so that it can take command-line arguments, like most Unix commands. Using command-line arguments is quite simple in most scripting and programming languages.
In all Unix shell scripts, the first argument is denoted by the special variable $1, the second by $2, and so on.
$0 refers to the name of the command as it was invoked.
In Bourne Shell family shells, we can find out how many command-line arguments were given by examining the special shell variable "$#". This is most often used to verify that the script was invoked with the correct number of arguments.
#!/bin/sh # If invoked incorrectly, tell the user the correct way if [ $# != 2 ]; then printf "Usage: $0 iterations output-file\n" exit 1 fi # Assign to named variables for readability iterations=$1 output_file="$2" # File name may contain white space! calcpi $iterations > "$output_file"
shell-prompt: calcpi-script Usage: calcpi-script iterations output-file shell-prompt: calcpi-script 1000 output-1000.txt shell-prompt: cat output-1000.txt 3.141723494
In C shell family shells, we can find out how many command-line arguments were given by examining the special shell variable "$#argv".
#!/bin/csh # If invoked incorrectly, tell the user the correct way if ( $#argv != 2 ) then printf "Usage: $0 iterations output-file\n" exit 1 endif # Assign to named variables for readability set iterations=$1 set output_file="$2" # File name may contain white space! calcpi $iterations > "$output_file"
shell-prompt: calcpi-script Usage: calcpi-script iterations output-file shell-prompt: calcpi-script 1000 output-1000.txt shell-prompt: cat output-1000.txt 3.141723494
Modify the following shell script so that it takes the file name of the dictionary and the sample word as user input instead of hard-coding it. You may use any shell you choose.
#!/bin/sh if fgrep 'abacus' /usr/share/dict/words; then printf 'abacus is a real word.\n' else printf 'abacus is not a real word.\n' fi