Selection from array


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Selection from array
# 1  
Old 10-05-2018
Selection from array

Hi,

I need some help taking a selection from a command and adding part of the output to an array.

I'd like to read the items into the array, have the user chose an option from the array and put the item from column 1 into a variable.

The command is:

Code:
awless -l list routetables --columns ID,NAME,VPC --filter VPC=vpc-0025xxxxxx94e52

The output from that command is:

Code:
|         ID ▲          |          NAME           |          VPC          |
|-----------------------|-------------------------|-----------------------|
| rtb-0b5c74xxxxxxx | network-public  | vpc-0025xxxxxx94e52 |
| rtb-0d18xxxxxxxxx | network-private | vpc-0025xxxxxd94e52 |
| rtb-0e47xxxxxxxxx |                         | vpc-0025xxxxxx94e52 |

and i want rtb-xxxxx to be in my variable (for now just print the variable is fine)

As you can see one option has no name. I'd like the options to be displayed showing both ID and name:

Code:
1. rtb-0b5c74xxxxxxx | network-public
2. rtb-0d18xxxxxxxxx | network-private
3. rtb-0e47xxxxxxxxx | NO-NAME

Thank you for your time.


Moderator's Comments:
Mod Comment Please use CODE tags as required by forum rules!

Last edited by RudiC; 10-05-2018 at 06:53 PM.. Reason: Added CODE tags.
# 2  
Old 10-05-2018
Quote:
Originally Posted by bignellrp
I need some help taking a selection from a command and adding part of the output to an array.
In general: to get qualified help with SHELL PROGRAMMING problems it usually helps to tell WHICH SHELL you are talking about. Sorry, but my crystal ball is in repair right now and mind reading is not part of the job description.

I suggest you read up on the select-command which many shells offer. It should do exactly what you have in mind. Have a look at the documentation of your shell and if it doesn't have it then report back - and tell us which shell that is.

I hope this helps.

bakunin
# 3  
Old 10-06-2018
Hi Bakunin,

Thanks for the reply. I had a read up on the select command and it does look like something that could solve this.

I'm using bash but my programming skills are poor and can't get the result I'm looking for.
# 4  
Old 10-06-2018
Could you confirm your belief that "it does look like something that could solve this", e.g. by trial and error? That were a possible (if not the usual) approach when encountering something new.


Howsoever, here's a small example how you could proceed. Unfortunately, I had to go through a TMP file, as piping the sed result directly into readarray failed, although its man page says: "Read lines from the standard input into the indexed array variable array"
Try and comment back

Code:
awless . . . | sed -r 's/( *)\| */\1/g; s/  / /g; s/[^ ]* *$//; > TMP
<TMP readarray -ts2 TARR
select OPT in "${TARR[@]}"
  do    echo "$REPLY: $REPLY, variable: $OPT, reduced var: ${OPT% * *}"
  done
1) rtb-0b5c74xxxxxxx network-public 
2) rtb-0d18xxxxxxxxx network-private 
3) rtb-0e47xxxxxxxxx 
#? 1
1: 1, variable: rtb-0b5c74xxxxxxx network-public , reduced var: rtb-0b5c74xxxxxxx
#? 2
2: 2, variable: rtb-0d18xxxxxxxxx network-private , reduced var: rtb-0d18xxxxxxxxx
#? 3
3: 3, variable: rtb-0e47xxxxxxxxx , reduced var: rtb-0e47xxxxxxxxx 
#?

# 5  
Old 10-06-2018
I can't get your script to work.

./test2
./test2: line 2: unexpected EOF while looking for matching `''
./test2: line 7: syntax error: unexpected end of file

Code:
#!/bin/bash
awless -l list routetables --columns ID,NAME,VPC  -filter VPC=vpc-00xxxxxxxxxxe52 | sed -r 's/( *)\| */\1/g; s/  / /g; s/[^ ]* *$//; > TMP
<TMP readarray -ts2 TARR
select OPT in "${TARR[@]}"
  do    echo "$REPLY: $REPLY, variable: $OPT, reduced var: ${OPT% * *}"
  done

------ Post updated at 09:43 AM ------

Just in case it helps here is my bad attempt that doesn't work. I thought posting my bad attempt might confuse the situation as I'm trying to find a simpler solution thats easier to replicate for other searches.

Code:
#!/bin/bash
q=1
for z in `awless -l list routetables --columns ID,NAME,VPC --filter VPC=vpc-00xxxxxxxxxxxe52  |\
 awk '
 /\| vpc/ && NF == 4 { print $2 ":No_Label" }
 /\| vpc/ && NF == 5 { print $2 ":" $4 }
 '`
 do
 array3[$q]=`echo $z | awk -F: ' { print $2 } '`
 array4[$q]=`echo $z | awk -F: ' { print $1 } '`
 echo "   $q. $z" ; q=$(($q + 1))
 done
 read selection2

 if [[ $selection2 =~ ^[0-9][0-9]*$ ]] ; then
  echo
 else
  echo "That selection was not valid"
  exit
 fi

 if [ ${array3[$selection2]} ] ; then
  arrayvar3="${array3[$selection2]}"
  arrayvar4="${array4[$selection2]}"
  echo "Thank you for your selection. I will use this for my script... $arrayvar3 $arrayvar4"
  echo ""
  echo "Processing....."
 else
  echo "That selection was not valid"
  exit
 fi

# 6  
Old 10-06-2018
First off: thank you for posting your script. It is a lot easier (and perhaps much better for you) to explain to you what you did wrong than to just envision a solution which yu don't understand where it comes from. It will not confuse the situation but in fact help clarify it. We do not want to solve your problem - we want to enable you to solve it on yourself.

Quote:
Originally Posted by bignellrp
Just in case it helps here is my bad attempt that doesn't work. I thought posting my bad attempt might confuse the situation as I'm trying to find a simpler solution thats easier to replicate for other searches.

Code:
#!/bin/bash
q=1
for z in `awless -l list routetables --columns ID,NAME,VPC --filter VPC=vpc-00xxxxxxxxxxxe52  |\
 awk '
 /\| vpc/ && NF == 4 { print $2 ":No_Label" }
 /\| vpc/ && NF == 5 { print $2 ":" $4 }
 '`
 do
 array3[$q]=`echo $z | awk -F: ' { print $2 } '`
 array4[$q]=`echo $z | awk -F: ' { print $1 } '`
 echo "   $q. $z" ; q=$(($q + 1))
 done
 read selection2

 if [[ $selection2 =~ ^[0-9][0-9]*$ ]] ; then
  echo
 else
  echo "That selection was not valid"
  exit
 fi

 if [ ${array3[$selection2]} ] ; then
  arrayvar3="${array3[$selection2]}"
  arrayvar4="${array4[$selection2]}"
  echo "Thank you for your selection. I will use this for my script... $arrayvar3 $arrayvar4"
  echo ""
  echo "Processing....."
 else
  echo "That selection was not valid"
  exit
 fi

Let us first sum up the goal: you want to create a selection menu from the output of a program. The output is roughly a table and each line will be a possible selection, yes?

Now, let us examine the description of the selection-keyword. Here it is (taken from my system, a Linux):

Code:
       select name [ in word ] ; do list ; done
              The list of words following in is expanded, generating a list of
              items.   The  set  of  expanded words is printed on the standard
              error, each preceded by a number.  If the in  word  is  omitted,
              the  positional  parameters  are printed (see PARAMETERS below).
              The PS3 prompt is then displayed and a line read from the  stan-
              dard  input.   If the line consists of a number corresponding to
              one of the displayed words, then the value of  name  is  set  to
              that  word.  If the line is empty, the words and prompt are dis-
              played again.  If EOF is read, the command completes.  Any other
              value  read  causes  name  to  be set to null.  The line read is
              saved in the variable REPLY.  The list is  executed  after  each
              selection until a break command is executed.  The exit status of
              select is the exit status of the last command executed in  list,
              or zero if no commands were executed.

So we first have to create a list of words. You already did this by creating the array. Let us set aside your problem for a moment to get us acquainted with the select-keyword. Here it is:

Code:
#! /bin/bash

arr[1]="apples"
arr[2]="bears"
arr[3]="peaches"
arr[4]="oranges"

selection=""

select selection in ${arr[@]} ; do
    echo "You selected $selection"
done

echo "here is the end of the program"
exit 0

Try that out on your own system. (Really! Try it! Don't just take my word for it.)

Now what did you find? First, the selection works smoothly. As long as you enter "1", "2", "3" or "4" everything works fine. What happens when you enter "0" or "17" or "blabla"? And how is the selection loop left? You probably figured out that you can use Ctrl-C to exit, but that is not a nice way to leave it. We would rather have something like "Press 1-4 for select a fruit or x to exit", yes?

Also there is this ridiculous prompt: Shouldn't there be something like, "Press..." as i said above, rather than "#?"? Let us start with this. There was this part of the documentation:

Quote:
The PS3 prompt is then displayed and a line read from the standard input.
So, we have to set the PS3 prompt (shell has 4 different prompts for certain situations. We usually see PS1, which it displays when waiting for the use to enter a command, but here PS3 is used) and we do that right before the start of the selection:

Code:
#! /bin/bash

arr[1]="apples"
arr[2]="bears"
arr[3]="peaches"
arr[4]="oranges"

selection=""

PS3="Enter 1-4 to select a fruit or x to exit => "
select selection in ${arr[@]} ; do
    echo "You selected $selection"
done

echo "here is the end of the program"
exit 0

Better, yes? But we should have a reaction of some sort when the user pressed a non-existing item, like "5" or "0" or "blabla". So we have to put some logic into the loop to react to that. Since we might need several cases we do not use if, but a case..esac:


Code:
#! /bin/bash

arr[1]="apples"
arr[2]="bears"
arr[3]="peaches"
arr[4]="oranges"

selection=""

PS3="Enter 1-4 to select a fruit or x to exit => "
select selection in ${arr[@]} ; do
     case "$selection" in
          "")
               echo "You selected a non-existing item"
               ;;

          *)
               echo "You selected $selection"
               ;;

     esac
done

echo "here is the end of the program"
exit 0

Why did this work? because the documentation said:

Quote:
If the line consists of a number corresponding to one of the displayed words, then the value of name is set to that word. [...] Any other value read causes name to be set to null.
That means, enter 1-4 and the value of "$selection" is set to the first-fourth element of our array. Enter any other value and the value of selection is set to "" (the null string). This is what we checked in the first case-branch, any other value means some "legal" value was entered.

We still did not implement a means of leaving the loop so we tackle this as next: we can simply add a special item to the array which selection causes the loop to be left:

Code:
#! /bin/bash

arr[1]="apples"
arr[2]="bears"
arr[3]="peaches"
arr[4]="oranges"
arr[5]="EXIT"

selection=""

PS3="Enter 1-4 to select a fruit or 5 to exit => "
select selection in ${arr[@]} ; do
     case "$selection" in
          "")
               echo "You selected a non-existing item"
               ;;

          "EXIT")
               echo "You are leaving the loop."
               break
               ;;

          *)
               echo "You selected $selection"
               ;;

     esac
done

echo "here is the end of the program"
exit 0

Notice that now, for a change, the line i put in next to the last line "here is the end of the program" was executed for the first time. We really and correctly left the program. It is also time now to make the whole thing a bit more "dynamic": right now, if we add another item, we would have to change not only the array and the number of the "EXIT" item, but also the PS3-prompt. We will make these to adjust automatically:

The number of elements in an array is in a variable expansion: "${#<arrayname>[@]}". So, to automatically add the "EXIT" item as the last item of the array we do:

Code:
arr[1]="apples"
arr[2]="bears"
arr[3]="peaches"
arr[4]="oranges"

arr[((${#arr[@]}+1))]="EXIT"

Notice that "((${#arr[@]}+1))" will always evaluate to the number of array elements plus 1. So now, it evaluates to "5", but if i remove the line with the oranges it would evaluate to "4" and if i would add a line it would evaluate to "6". We do something similar to the PS3 prompt:

Code:
PS3="Enter 1-$((${#arr[@]}-1)) to select a fruit or ${#arr[@]} to exit => "

Notice that since the EXIT-selection will have a varying index but always the same value (the string "EXIT") we do not need to change the loop itself. So here is our script, were you can remove or add items to the initial array without changing anything else:

Code:
#! /bin/bash

arr[1]="apples"
arr[2]="bears"
arr[3]="peaches"
arr[4]="oranges"

arr[((${#arr[@]}+1))]="EXIT"

selection=""

PS3="Enter 1-$((${#arr[@]}-1)) to select a fruit or ${#arr[@]} to exit => "

select selection in ${arr[@]} ; do
     case "$selection" in
          "")
               echo "You selected a non-existing item"
               ;;

          "EXIT")
               echo "You are leaving the loop"
               break
               ;;

          *)
               echo "You selected $selection"
               ;;

     esac
done

echo "here is the end of the program"
exit 0

I will stop here now, because you are sure anxious to try your newfound toy and play around with it. I also suggest that when you write scripts you do the indenting like i do and not like you did. Experience shows that it is easier to discern the program flow and the structure that way.

Have fun and if you still have questions don't hesitate to ask.

I hope this helps.

bakunin
These 3 Users Gave Thanks to bakunin For This Post:
# 7  
Old 10-06-2018
Wow. Thanks so much bakunin. You are certainly right that it is better to "teach a man to fish". I struggled with this for hours before i posted as it was hard finding something on google that was relevant enough to my problem to learn from. So now not only am i one step closer to resolving my problem i have learned a lot more.

I'll have a play and let you know how i get on.

------ Post updated at 05:24 PM ------

Having much more fun now i know how the array works, but I'm struggling to get the row to display as a whole selection. The array is splitting all the individual items into options.

I want to display like:

1. apples : 1111 : aaaa
2. pears : 2222 : bbbb
3. peaches : 3333 : cccc

but its displaying

1. apples
2. 1111
3. aaaa
4. pears
5. 2222

etc

Here is my new code:

Code:
options=( $(awless -l list routetables --columns ID,NAME,VPC --filter VPC=vpc-0025xxxxxxxe52 | grep rtb | sed 's/|//g') )
selection=""
options[((${#options[@]}+1))]="EXIT"

selection=""

PS3="Enter 1-$((${#options[@]}-1)) to select an item or ${#options[@]} to exit => "

#PS3="Select an item or 5 to exit => "
select selection in ${options[@]} ; do
     case "$selection" in
          "")
               echo "You selected a non-existing item"
               ;;

          "EXIT")
               echo "You are leaving the loop."
               break
               ;;

          *)
               echo "You selected $selection"
               ;;

     esac
done

echo "here is the end of the program"
exit 0

Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

If Selection statement

ok im kinda stuck i have a bash script with 4 options 1. Create Script 2. Show Script 3 . Delete script 4. Exithow would i use an if statement for this? im not sure what test command i would use. I know it would be like this (below) to display the script if then cat script1or for the... (10 Replies)
Discussion started by: gangsta
10 Replies

2. Shell Programming and Scripting

Date selection

Hi All, i have log file sample data is 2010/10/09|04:00:00.392|15Minute|BW=0|192.168.0.1 2010/10/08|04:00:00.392|15Minute|BW=0|192.168.0.1 2010/10/07|04:00:00.392|15Minute|BW=0|192.168.0.1 2010/10/05|04:00:00.392|15Minute|BW=0|192.168.0.1 2010/10/03|04:00:00.392|15Minute|BW=0|192.168.0.1... (2 Replies)
Discussion started by: posner
2 Replies

3. UNIX for Dummies Questions & Answers

awk for column selection

Hello, I want to extract all values from table except for those that contain the '*' character in the second column. I tried awk '$2!=*' and this threw a syntax error. Do I need to specify an escape character or != is valid only for numerical comparisons? Thanks, Guss (1 Reply)
Discussion started by: Gussifinknottle
1 Replies

4. AIX

Bulk Fixes Selection

Under smit, one has to manually select each fix with F7. there 9000 fixes left to be marked. How Can I manually install/Mark all of these without SMIT. ---------- Post updated at 02:29 PM ---------- Previous update was at 01:15 PM ---------- From the command line instfix -T -d... (4 Replies)
Discussion started by: mrmurdock
4 Replies

5. Shell Programming and Scripting

Data selection

Hi, Please note that as a programmer I cannot tell the file format or details of my production files so I have re-framed my file and taken a case of departments. Kindly guide as its related to a production requirement of data containing recors of production customer NOT A HOMEWORK :) I have... (10 Replies)
Discussion started by: test_user
10 Replies

6. Shell Programming and Scripting

Data selection

Hi, I have a file containing details of different departments . Infomration of departments is in various tags file is as below I want to create a new file from the above file which should contain only two fields belonging to one department format There are multiple files... (1 Reply)
Discussion started by: test_user
1 Replies

7. Shell Programming and Scripting

Menu help with array selection

Hi there all I got the following I got multiple arrays named for example STAT_AAAA STAT_AAAB STAT_AAAC STAT_AAAD Now what I want I have chosen an option in a menu to select 1 but I dont want to write for all the same thing so I made it a signle one now what I want is to get STAT_ and... (6 Replies)
Discussion started by: draco
6 Replies

8. Post Here to Contact Site Administrators and Moderators

Opt out selection

Maybe I'm missing something but when I go to CP->Options, I see the box for selecting which forum to opt out of but no way to set it. (5 Replies)
Discussion started by: drhowarddrfine
5 Replies

9. UNIX for Advanced & Expert Users

tray selection

Hello All, Could anyone help me how to selecting the trays in unix . Thanks, Amit kul (3 Replies)
Discussion started by: amit kul
3 Replies

10. Shell Programming and Scripting

Array and Selection

I have a question: Y X Tabel a is a array multidimensional --> a(1024,20) I load in to array a Text from 6000 row where: in a(1,1) is present the row 1 of original text, in a(1024,1) is present then row 1024 of original test and in... (4 Replies)
Discussion started by: ZINGARO
4 Replies
Login or Register to Ask a Question