LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 11-19-2011, 09:29 AM   #1
kcleveland
LQ Newbie
 
Registered: Jun 2010
Posts: 28

Rep: Reputation: 0
Question Shell scripting - for...in loop and variables question


I'm trying to re-write a script that we use to monitor some switches in our lab. The number is growing, and I need to start using a loop to check the different stacks.

My problem is that I cannot get the variable name to change and get the value written to the new variable dependent upon the for loop's iteration.

Here is one of the snippets I'm trying to re-script:

Code:
#!/bin/bash
#Get the temp of Stack 1
unitNum=1

for host in $iplist

    do

          stack1unit${unitNum}=$(snmpget ${host} -v 2c -c public .1.3.6.1.4.1.45.1.6.3.7.1.1.5.5.${unitNum}0.0 | awk -F":" '{print $2}')

          let unitNum=$unitNum+1

    done
As you can see, I'm trying to take the value returned from the snmpget and assign it to a variable whose name is determined by the values of the iteration of the loop.

It should create variables named stack1unit1, stack1unit2, stack1unit3, and stack1unit4 whose values are obtained from the snmpget output.


As you can probably tell, I can't get it to work (snmp stuff works fine-I need no help on that part - it is the variable creation from the loop iteration that I can't get working). I have tried eval with no luck, and can't wrap my head around how indirectly referencing the variable could help me.

Also, if we do manage to create these variables properly, will they still be available once the loop terminates?

Can anyone please shed some light on this for me?

Thanks!
 
Old 11-19-2011, 10:11 AM   #2
millgates
Member
 
Registered: Feb 2009
Location: 192.168.x.x
Distribution: Slackware
Posts: 852

Rep: Reputation: 389Reputation: 389Reputation: 389Reputation: 389
what does the output of $(...) look like?

Quote:
Originally Posted by kcleveland
I have tried eval with no luck
What have you tried? What did you get? Were there any error messages?

this works for me:
Code:
$ NUM=1
$ eval FOO${NUM}=bar
$ echo $FOO1
bar
have you considered using arrays instead?

Quote:
Also, if we do manage to create these variables properly, will they still be available once the loop terminates?
as long as they are not created in a context executed in a subshell, yes. In your case the variables will exist outside the loop
 
Old 11-19-2011, 10:14 AM   #3
Juako
Member
 
Registered: Mar 2010
Posts: 202

Rep: Reputation: 84
Try

Code:
read -r stack1unit${unitNum} <<< $(snmpget ${host} -v 2c -c public .1.3.6.1.4.1.45.1.6.3.7.1.1.5.5.${unitNum}0.0 | awk -F":" '{print $2}')
 
Old 11-19-2011, 10:22 AM   #4
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
Why not simply use an array??
 
Old 11-19-2011, 10:35 AM   #5
firstfire
Member
 
Registered: Mar 2006
Location: Ekaterinburg, Russia
Distribution: Debian, Ubuntu
Posts: 709

Rep: Reputation: 428Reputation: 428Reputation: 428Reputation: 428Reputation: 428
Hi.

You can create variables stack1unit1 ... stack1unit4 using, e.g.
Code:
export stack1unit${unitNum}=$(...)
You can access their values by $stack1unit1 etc, even outside the loop.
For example:
Code:
$ for n in `seq 1 3`; do echo $n; export x$n=$n ; done
1
2
3
$ echo $x1
1
$ echo $x2
2
$ echo $x3
3
But I can't see how to access their values by index. For example
Code:
n=3
echo $x$n
did not work.

I think you should definitely use bash arrays for that.
 
Old 11-19-2011, 10:44 AM   #6
Juako
Member
 
Registered: Mar 2010
Posts: 202

Rep: Reputation: 84
Quote:
Originally Posted by firstfire View Post
Hi.
You can create variables stack1unit1 ... stack1unit4 using, e.g.
Code:
export stack1unit${unitNum}=$(...)
Now that's better than read, should work with local/declare too if you want smaller scopes than all children of the script.

Quote:
Originally Posted by firstfire View Post
But I can't see how to access their values by index.
For that use ${!} :
Code:
#!/bin/bash
for n in `seq 1 3`; do echo $n; declare x$n="value: $n" ; done
for n in `seq 1 3`; do
    temp="x$n"
    echo "${!temp}"
done
But this is all very clunky anyway, arrays are designed for this very task: looping a group of related data.
 
Old 11-19-2011, 10:50 AM   #7
kcleveland
LQ Newbie
 
Registered: Jun 2010
Posts: 28

Original Poster
Rep: Reputation: 0
Thanks for all of the suggestions!

I'm going to try several of them out right now and will post back with the one I wind up using.
 
Old 11-19-2011, 10:51 AM   #8
firstfire
Member
 
Registered: Mar 2006
Location: Ekaterinburg, Russia
Distribution: Debian, Ubuntu
Posts: 709

Rep: Reputation: 428Reputation: 428Reputation: 428Reputation: 428Reputation: 428
Quote:
Originally Posted by Juako View Post
For that use ${!} :
Wow! Good thing to know.. Thanks.
 
Old 11-19-2011, 11:11 AM   #9
kcleveland
LQ Newbie
 
Registered: Jun 2010
Posts: 28

Original Poster
Rep: Reputation: 0
I wound up using Juako's read command - it just seemed to be the easiest.

However, I must admit I do not understand why it works. I know the read command will read a line at a time from standard input, but its the "<<<" that's got me fooled (its not east to google those characters

Can you guys explain to me the mechanics behind the "<<<"?

Thanks!
 
Old 11-19-2011, 11:16 AM   #10
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
read is no longer read from standard input but rather from the herestring (<<<). You can look here for details.
 
Old 11-19-2011, 11:17 AM   #11
Juako
Member
 
Registered: Mar 2010
Posts: 202

Rep: Reputation: 84
Quote:
Originally Posted by kcleveland View Post
I wound up using Juako's read command - it just seemed to be the easiest.

However, I must admit I do not understand why it works. I know the read command will read a line at a time from standard input, but its the "<<<" that's got me fooled (its not east to google those characters

Can you guys explain to me the mechanics behind the "<<<"?

Thanks!
"<<<" is "send a string to standard input", called "herestring".

But read up from firstfire's post, that's even easier:

Code:
declare -x stack1unit${unitNum}=$(snmpget ${host} -v 2c -c public .1.3.6.1.4.1.45.1.6.3.7.1.1.5.5.${unitNum}0.0 | awk -F":" '{print $2}')

echo $stack1unit1
for (dynamic I assume) indirect reference the variables:
Code:
name="stack1unit1"
echo "${!name}"
 
Old 11-20-2011, 04:07 AM   #12
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
For the record, $(..) operates as a subshell. There's no way to access any variables set inside it from the outside. You have to arrange the command so that the substitution itself outputs all the values you want, or so that the value you want is produced outside of the subshell.

But as grail mentioned first, and others have repeated, you really, Really, REALLY should be using an array for this, rather than trying to generate dynamic scalar variable names.

Just use stack1unit[${unitNum}]=, and you will have entries of ${stack1unit[0]} ${stack1unit[1]} ${stack1unit[2]}, etc. that you can use later on. If you need the indexes to be text strings instead, you can even use an associative array (assuming bash 4+)

http://mywiki.wooledge.org/BashGuide/Arrays
http://mywiki.wooledge.org/BashFAQ/006

The second link is for reference only. You really should be using an array for this.


Oh, and by the way, did I mention that you really should be using an array for this?

Last edited by David the H.; 11-20-2011 at 04:14 AM. Reason: added link
 
Old 11-20-2011, 08:17 AM   #13
Juako
Member
 
Registered: Mar 2010
Posts: 202

Rep: Reputation: 84
Yup agreed, (dynamic) indirect vars definitely have their uses where they're better than arrays, but this doesn't seem to be the case IMO.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
how can we use multiple variables in single for loop in shell script nagendrar Linux - Newbie 11 05-22-2017 01:21 PM
Shell scripting question - joining variables or variable + text Xyan Linux - General 6 01-03-2009 11:54 AM
shell variables becoming zero outside the loop cool244 Programming 4 05-20-2006 03:33 PM
shell variables losing value outside while loop cool244 Programming 1 05-19-2006 10:04 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:55 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration