It is a sad fact that the UNIX shell is not a high level programming language--consequently, effective shell coding often involves arcane tricks. In this section, we'll provide some useful templates for some of the common UNIX shell programming idioms.
We use CvStack as an illustration. The core of this shell is a double loop over velocities and cdps that produces velocity panels--a concept not contained in any single SU program.
Remark: For most of us, writing a shell like CvStack from scratch is a time-consuming affair. To cut down the development time, your authors excerpt from existing shells to make new ones even when we don't quite remember what every detail means. We suggest that you do the same!
We won't comment on the lines already explained in our previous two shell code examples (see Sections 8.2.1 and 8.2.3), but instead focus on the new features used in CvStack.
#! /bin/sh
# Constant-velocity stack of a range of cmp gathers
# Authors: Jack, Ken
# NOTE: Comment lines preceding user input start with #!#
set -x
#!# Set input/output file names and data parameters
input=cdp601to610
stackdata=cvstack
cdpmin=601 cdpmax=610
fold=30
space=1 # 1 null trace between panels
#!# Determine velocity sampling.
vmin=1500 vmax=3000 dv=150
### Determine ns and dt from data (for sunull)
nt=`sugethw ns <$input | sed 1q | sed 's/.*ns=//'` [1]
dt=`sugethw dt <$input | sed 1q | sed 's/.*dt=//'`
### Convert dt to seconds from header value in microseconds
dt=`bc -l <<END [2]
scale=4
$dt / 1000000
END`
### Do the velocity analyses.
>$stackdata # zero output file [3]
v=$vmin
while [ $v -le $vmax ] [4]
do
cdp=$cdpmin
while [ $cdp -le $cdpmax ] [5]
do
suwind <$input \ [6]
key=cdp min=$cdp max=$cdp count=$fold |
sunmo cdp=$cdp vnmo=$v tnmo=0.0 |
sustack >>$stackdata
cdp=`bc -l <<END [7]
$cdp + 1
END`
done
sunull ntr=$space nt=$nt dt=$dt >>$stackdata [8]
v=`bc -l <<END
$v + $dv
END`
done
### Plot the common velocity stacked data
ncdp=`bc -l <<END
$cdpmax-$cdpmin+1
END`
f2=$vmin
d2=`bc -l <<END
$dv/($ncdp + $space) [9]
END`
sugain <$stackdata tpow=2.0 |
suximage perc=99 f2=$f2 d2=$d2 \
title="File: $input Constant-Velocity Stack " \
label1="Time (s)" label2="Velocity (m/s)" &
exit [10]
Discussion of numbered lines:
% suplane | sugethw tracl ns tracl=1 ns=64 tracl=2 ns=64 tracl=3 ns=64 tracl=4 ns=64 tracl=5 ns=64 tracl=6 ns=64 ...Although sugethw is eager to give the values for every trace in the data set, we only need it once. The solution is to use the UNIX stream editor (sed). In fact, we use it twice. By default, sed passes along its input to its output. Our first use is merely to tell sed to quit after it puts the first line in the pipe. The second pass through sed strips off the unwanted material before the integer. In detail, the second sed command reads: replace (or substitute) everything up to the characters
ns= with nothing, i.e., delete
those characters.
dt. The calculation may take several lines.
We first set the number of decimal places with scale=4
and then do the conversion to seconds. The characters END
that follow the here document redirection symbol << are arbitrary,
the shell takes its input from the text in the shell file
until it comes to a line that contains the same
characters again. For more information about bc:
% man bc
> always does as its first action--it's a dangerous
operator! If you intend to append, then, as mentioned earlier, use
>>.
Caveat: The bracket notation is a nice
alternative to the older clunky test notation:
while test $v -le $vmaxBecause the bracket notation is not documented on the typical sh manual page, we have some qualms about using it. But, as far as we know, all modern sh commands support it--please let us know if you find one that doesn't.
WARNING! OK, now you know that there is a UNIX command
called test. So don't use the name ``test'' for one of your
shell (or C) programs--depending on your $PATH setting, you could
be faced with seemingly inexplicable output.
END against the left margin. That's because
the sh manual page says that the termination should contain
only the END (or whatever you use). In fact, most versions
support indentation. We didn't think the added beautification was
worth the risk in a shell meant for export. Also note that we used
bc for an integer arithmetic calculation even though
integer arithmetic is built into the Bourne shell--why learn
two arcane rituals, when one will do? See man expr, if
you are curious.
CvStack.
Actually, I had written this program many times, but this was the first
time I did it on purpose. (Yes, that was an attempt at humor.)
exit statement is useful because you might want
to save some ``spare parts'' for future use. If so, just put them
after the exit statement and they won't be executed.
Figure 8.2 shows an output generated by CvStack.