OK. Finally, here it is. The following Korn shell script provides a way to read a data file (named data ), extract data items from that file, create a menu of the data items, and allows the user to interactively request the data associated with each menu entry. It actually provides two sample solutions for this problem and runs both solutions so the user can see the differences in behavior.
The first method is an awk script. It only uses features in awk that are included in the POSIX Standards. (Note that on Solaris systems, you'll need to use nawk or /usr/xpg4/bin/awk rather than /usr/bin/awk.)
The second method is a Korn shell script. It makes use of a few features that are not available in old versions of ksh; you'll need a version newer than November 16, 1988. It also makes use of some features that are not required by the POSIX standards.
The awk and ksh scripts use the same variable names. A summary of the variable names and their uses is provided in comments between the two scripts.
Here it is:
#!/bin/ksh
echo '*** 1st method: Using awk script... ***'
# Note that the variable names used in this awk script use the same variable
# names as the shell variables in the ksh script below. A list of the
# variables and their use is included below for the ksh script.
#
# Note also that the echo and cat here are critical to allow awk to detect the
# EOF on the data file and display the prompt for the first round of
# interactive user input...
(echo;cat)|awk 'BEGIN{m = "Menu of options:\n"}
function mp(){printf("\n%s", m)}
{ # Throw away leading and trailing whitespace on all input.
sub(/^[[:space:]]*/, "")
sub(/[[:space:]]*$/, "")
}
FNR == NR {
# We are reading the data file here...
if($0 == "") next # skip blank lines, sub() above made blank lines empty
if($0 == "!")
# Note that next non-empty data line starts a menu entry
d1=1
else if(d1) {
# First line in data for menu choice mc, create menu entry
d[++mc] = $0 "\n"
d1=0
m = sprintf("%s%d %s\n", m, mc,
match($0, /[^[:alpha:]]/) > 0 ? \
substr($0, 1, RSTART - 1) : $0)
} else # Subsequent line in data for menu choice mc
d[mc] = d[mc] $0 "\n"
next
}
FNR == 1 {
# We are reading the line produced by the echo here. Finish up the
# menu, print the menu, and wait for the user to enter a selection:
m = sprintf("%sEnter your choice 1 to %d (ctl-D to exit):\n", m, mc)
mp()
next
}
{ if($0 ~ /[^[:digit:]]/ || $0 < 1 || $0 > mc) printf("Invalid choice.\n")
else printf("%s", d[$0])
mp()
}' data -
sleep 1
echo '*** 2nd method: Just using ksh... ***'
# Shell variable data dictionary:
# d[x] "d"ata for menu item x
# d1 != 0 => looking for "d"ata line #"1" for menu entry $mc
# in current "in"put line
# m "m"enu
# mc "m"enu entry "c"ount
d1=0
m='Menu of options:'
while read -r in
do if [[ "$in" == '' ]]
then continue # skip empty lines in data file
elif [[ "$in" == '!' ]]
then d1=1 # Next non-blank line is where we'll find the
# menu text and the start of the data text.
elif [[ $d1 == 1 ]]
then # Gather data from 1st data line for a menu item.
((mc++))
d[mc]="$(printf '%s\n' "$in")" # 1st line of data
# Add a selection line to the menu.
m="$(printf '%s\n%d %s' "$m" $mc "${in/%[^[:alpha:]]*/}")"
d1=0 # no longer looking for the 1st data line
else # Add another line of data to the current entry.
d[mc]="$(printf '%s\n%s' "${d[mc]}" "$in")"
fi
done < data
m="$(printf '%s\nEnter your choice 1 to %d (ctl-D to exit): ' "$m" $mc)"
while printf '\n%s' "$m" # Print the menu
do if ! read -r in # read the user's menu selection
then echo # user entered ctl-d, reposition cursor & exit
exit
fi
# Verify that the user's respons was not an empty line, didn't contain
# any non-digit characters, and is a number between 1 and $mc inclusive.
if [[ in == '' || ${in//[[:digit:]]/} != '' || in -lt 1 || in -gt mc ]]
then echo 'Invalid choice.'
continue
fi
# We have a verified entry, print the selected data item.
printf '%s\n' "${d[$in]}"
# Give the user a few seconds to read the results before reprinting the
# menu...
sleep 2
done
and here is the data file I used to test it:
!
version 12.4
service timestamps debug datetime msec
service timestamps log datetime msec
no service password-encryption
!
hostname MarcsTestbox
!
boot-start-marker
boot-end-marker
!
logging message-counter syslog
enable secret {FIELD DELETED] [FIELD DELETED]
!
no aaa new-model
clock timezone
!
etc.
.
.
.
The first part of it is data that was provided in the 1st message in this thread, but adds some spaces and tabs at the beginning and end of some non-empty lines, and adds some blank lines to test the ability of these scripts to handle blank lines, leading whitespace, and trailing whitespace.
I hope this helps you compare some of the features of awk and ksh for performing similar tasks.