LinuxQuestions.org
Support LQ: Use code LQ3 and save $3 on Domain Registration
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 02-03-2013, 01:05 AM   #1
soupmagnet
LQ Newbie
 
Registered: Sep 2012
Posts: 27

Rep: Reputation: Disabled
Need to generate an array based on user input


I need to generate a range of variables based on user input. The user will first choose the number of variables in the range, then assign a value to each of the variables. I'm trying to do this in a loop but I'm running into problems.

This is what I have to create the range of variables:

Code:
read -p "Enter a number for range of variables: " foo

myfunction(){ 
(( bar = $foo + 1 ))
let count=1
until [ $count -eq $bar ]; do
echo var"$count"
(( count = $count + 1 ))
done | tr "\n" " " | sed 's/\ $//'
}
If the user enters 5, the output will be
Code:
var1 var2 var3 var4 var5
If I try to assign a value to each of the variables things get kind of weird.

Code:
for i in `myfunction`; do
  read -p "Enter a value" value
  let $i=$value
  echo $i
  echo $var1
done
...which outputs
Code:
var1
0
...if the value is a string,

but
Code:
1234
<empty line>
if the value is a number.

Why isn't the value being assigned to the variable?
 
Old 02-03-2013, 08:45 AM   #2
millgates
Member
 
Registered: Feb 2009
Location: 192.168.x.x
Distribution: Slackware
Posts: 651

Rep: Reputation: 269Reputation: 269Reputation: 269
let treats the expression as an arithmetic expression, so if you pass a string there, don't expect to get anything reasonable.
What are you trying to do in the first place?
Why don't you just use arrays?
 
1 members found this post helpful.
Old 02-03-2013, 10:29 AM   #3
soupmagnet
LQ Newbie
 
Registered: Sep 2012
Posts: 27

Original Poster
Rep: Reputation: Disabled
I'm working on a repartitioning script for Android

I know I can do something like this...
Code:
name1=boot; name2=system; name3=data; name4=cache; name5=media
size1=11; size2=500; size3=900; size4=256; size5=5000

NAME=(0 $name1 $name2 $name3 $name4 $name5)
SIZE=(0 $size1 $size2 $size3 $size4 $size5)

for i in {1..5}; do
  echo ${NAME[$i]}
  echo ${SIZE[$i]}
done
I have the majority of the script finished and working properly, but I want to add an option to let users choose not only the names and sizes of the partitions, but also the overall number of partitions.

I'm trying to figure out a way to assign a value to a string of text, as it's created in the script, based on the user's input.


I figured that was the case with the 'let' command, but trying to do something like...
Code:
$i=$value
will give an error
I've also tried...
Code:
`echo $i`=`echo $value`
but I receive the same error "command not found"

I'm trying to do it this way because the values of 'size1 size2 size3 etc...' can be changed at any point and I want to be able to use one script and just plug in the new values of those variables.

Does that make any sense at all?


I guess when it's all said and done, I'd like to be able to change the values of the variables in both $NAME and $SIZE, on the fly. Is that possible?

Last edited by soupmagnet; 02-03-2013 at 10:53 AM.
 
Old 02-03-2013, 03:32 PM   #4
millgates
Member
 
Registered: Feb 2009
Location: 192.168.x.x
Distribution: Slackware
Posts: 651

Rep: Reputation: 269Reputation: 269Reputation: 269
You can probably accomplish this with declare or even read

Code:
foo=bar
declare $foo=4
echo $bar
Code:
foo=bar
read $foo
echo $bar
It can also be done using eval, but I would strongly advise against that, because it's ugly and insecure.

I still think your best bet is to use arrays.

something like

Code:
read -a vars
will read the entire line in to an array, word per element. You can then iterate trough the array as

Code:
for i in "${vars[@]}"; do #iterating over the values
    echo "$i"
done
or

Code:
for i in "${!vars[@]}"; do #iterating over the indices
    echo "${vars[i]}"
done
This would work correctly regardless of the number of names in the input.

If you want to read the names, one per line, you can do something like

Code:
declare -a names

#read the number of elements
read number;

# read the names, one per line
for ((i = 0; i < number; i++)); do
    read -p "Enter value of name $i" names[i]
done
yet another way:

Code:
read -p "enter number of names: " number
echo "Enter $number names, one per line"
mapfile -n $number -t vars
echo "names entered:"
for i in "${vars[@]}"; do
   echo "$i"
done

Last edited by millgates; 02-03-2013 at 03:42 PM.
 
1 members found this post helpful.
Old 02-03-2013, 06:00 PM   #5
soupmagnet
LQ Newbie
 
Registered: Sep 2012
Posts: 27

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by millgates View Post
You can probably accomplish this with declare or even read
...
OH I SEE...

Agreed, that is much more effective than what I was trying to do. Thank you very much for your help.
 
Old 02-04-2013, 05:59 AM   #6
konsolebox
Senior Member
 
Registered: Oct 2005
Distribution: Gentoo, Slackware, LFS
Posts: 2,245
Blog Entries: 15

Rep: Reputation: 233Reputation: 233Reputation: 233
Quote:
Originally Posted by soupmagnet View Post
I'm trying to figure out a way to assign a value to a string of text, as it's created in the script, based on the user's input.
Associative arrays are the best solutions for that if you use Bash 4.0+.
 
2 members found this post helpful.
Old 02-04-2013, 01:22 PM   #7
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949
+1 to konsolebox. I was thinking the same thing.

How can I use array variables?
http://mywiki.wooledge.org/BashFAQ/005

The reason being that trying to create and use dynamic variable names is difficult and non-transparent.

How can I use variable variables (indirect variables, pointers, references) or associative arrays?
http://mywiki.wooledge.org/BashFAQ/006

Associative arrays let you use the same base array name, with a separate index for each string given. This means there's no need to worry about the limitations on variable names. They're much cleaner, safer, and easier to use than indirect variable creation.

Just be sure to declare the array globally, and not inside the function, if the values need to be used outside of it (although bash 4.2 has a new -g option to declare that you can use instead).

In addition:
Code:
for i in `myfunction`; do
Don't Read Lines With For!!

This is an incredibly common mistake. A for loop is for iterating over a list of words. But if there's whitespace involved then you cannot safely generate a list with a command substitution like this, due to the shell's word-splitting. You need to use a while+read loop or some other technique.

PS: $(..) is highly recommended over `..`

PPS: External tools like tr and sed can often be replaced by bash's built-in string manipulation features.
 
1 members found this post helpful.
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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
[SOLVED] Perform an action on a list/array of variables from user input in bash eamesj Programming 1 12-30-2012 10:22 PM
[SOLVED] Using powers based on user input curious95 Programming 3 11-28-2012 05:41 AM
Array size base on user input ICO Programming 1 10-27-2010 01:40 PM
Sorting through associative array with user input nobody123 Linux - Newbie 3 04-08-2009 01:55 PM
C++: user input to an int array? andrw123 Programming 12 09-22-2008 11:55 PM


All times are GMT -5. The time now is 11:25 AM.

Main Menu
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
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration