# Need a very simple loop for a script

Trying to write a script which uses Charles Karney's `GeodSolve` to solve a straight-forward geodesic problem. GeodSolve takes the input: lat1 lon1 azi1 dist1, and outputs: lat2 lon2 azi2.

I have a file ("azi_dist_file") containing azimuths and distances in the first and second column respectively. In the below simple script the user is asked to provide the initial position, lat1 and lon1, while azi1 and dist1 are fetched from azi_dist_file. The programme `GeodSolve` will then solve the direct geodesic problem and return the endpoint position, lat2 lon2 (and azi2 which is irrelevant here); I'd like this second position to be used as the initial position in a further invocation of `GeodSolve`, but fetching azi2 and dist2 from the 2nd row of azi_dist_file; repeated until the last row in that file is reached. Finally, I'd like all the lat,lon,azi,dist values written to a new file.

So far I have managed to write the following.

``````#!/bin/bash
echo "Enter starting latitude: "
read lat1
echo "Enter starting longitude: "
read lon1
alpha1=`awk 'NR==1{print;exit}' azi_dist_file|cut -f1 -d\$'\t'`
dist1=`awk 'NR==1{print;exit}' azi_dist_file|cut -f2 -d\$'\t'`
echo "\$lat1 \$lon1 \$alpha1 \$dist1" >> lat_lon_azi_dist_file
echo \$lat1 \$lon1 \$alpha1 \$dist1 | GeodSolve
lat2=`echo \$lat1 \$lon1 \$alpha1 \$dist1 | GeodSolve | cut -f1 -d' '`
lon2=`echo \$lat1 \$lon1 \$alpha1 \$dist1 | GeodSolve | cut -f2 -d' '`
echo "\$lat2 \$lon2"
``````
• Please edit your question and show us an example of your input file. Also, clarify what your script can do so far (much easier than having us figure it out from your code) and what it doesn't. Finally, as a general rule, I'd avoid expecting input from the user. It is much easier to pass the starting values as parameters to your script (`script.sh lat1 lat2`). The values will then be available to the script as `\$1` and `\$2` respectively.
– terdon
Sep 13, 2016 at 15:44

## 1 Answer

It sounds like you want something like:

``````#!/bin/bash -
# lat/lon passed as arguments to the script instead of being input to the
# user:
lat=\${1?} lon=\${2?}

while read alpha dist ignore; do
printf '%s\n' "\$lat \$lon \$alpha \$dist" >&3
read lat lon ignore < <(
printf '%s\n' "\$lat \$lon \$alpha \$dist" | GeodSolve 3>&-)
printf '%s\n' "\$lat \$lon"
done < azi_dist_file 3> lat_lon_azi_dist_file
``````

The `read vars < <(cmd)` is to work around the fact that in `bash` (contrary to `zsh` or AT&T `ksh`) in `cmd | read vars`, the `read` command is run in a subshell. Alternatively, with recent versions of `bash`, you can use `shopt -s lastpipe` to have `bash` behave like `zsh` or `ksh` in this instance.

POSIXly, you can also use:

``````unset -v IFS; set -f; set -- \$(cmd); lat=\$1 lon=\$2
``````