I grew up scripting with the C shell (csh), and I'm still more comfortable with it than any other shells. However, for really complicated scripts I find that BASH (the Bourne-again shell) is more flexible. The problem is that I don't really know how to use it all that well.
I could buy a book, I suppose, but that costs money. And anyway, much of what I want is already on the web. For example, we have
- The BASH Reference Manual
- The BASH Guide for Beginners
- The Advanced BASH Scripting Guide
- Handling Command Line Arguments
I've used all of these, but the only way to really remember something is to build an example, and refer back to it as needed. So here, presented for your consideration, are a couple of examples.
The first one just counts. It's basically here to show how to do math with variables in BASH:
#! /bin/bash typeset -i count count=$1 echo $count while (( $count < $2 )) do count=$count+1 echo $count done
Actually, that one is adapted from the Korn shell (ksh), but it works in bash. A purer bash form would be
#! /bin/bash let count=$1 echo $count while (( $count < $2 )) do let count=$count+1 echo $count done
Either way, if we call the file count, then it counts from the first argument up to the second:
./count 5 10 5 6 7 8 9 10
On to another program. I often have programs that recompute a certain quantity repeatedly, say the total energy in a Density Functional Theory run. For example,
$ grep "TOTAL ENERGY=" INFO
                          TOTAL ENERGY=      -551.5802151120
                          TOTAL ENERGY=      -551.5798689965
                          TOTAL ENERGY=      -551.5810124810
                          TOTAL ENERGY=      -551.5809217653
                          TOTAL ENERGY=      -551.5796453493
                          TOTAL ENERGY=      -551.5797608209
                          TOTAL ENERGY=      -551.5806860076
                          TOTAL ENERGY=      -551.5804690663
                          TOTAL ENERGY=      -551.5793575483
                          TOTAL ENERGY=      -551.5794583810
where I only want the last line. For a single file, I could get that with
$ grep "TOTAL ENERGY=" INFO | tail -1
                          TOTAL ENERGY=      -551.5794583810
but I want to look at multiple files, make a note of the file I'm looking at, and extract the last entry. So I wrote this little script, which I call lastgrep. Among other things, it shows you how to use the shift command to delete elements from the calling string.
#! /bin/bash
# usage
# lastgrep string  file1 file2 file3 file4
# finds the last occurrence of string in each of the files
#  listed in the argument list.  If string contains white space
#  it should be quoted
string=$1
# Pop the first argument (string) off the stack.  The
#  remaining arguments should be files
shift
for file in $@
do
    echo -n $file
#    Put quotes around $string to keep white space in place
    grep "$string" $file | tail -1
done 
So if I have a set of files INFO in directories a100, a200, a300, I might do something like this:
$ lastgrep "TOTAL ENERGY=" a*/INFO a100/INFO TOTAL ENERGY= -551.7810244761 a200/INFO TOTAL ENERGY= -551.6774784178 a300/INFO TOTAL ENERGY= -551.6192819148
What this doesn't have is a way of passing arguments to grep. That's for another time.
 

 
 Posts
Posts
 
 
 
 
 
 
0 comments:
Post a Comment