This question already has answers here:
Dynamic variable names in Bash
(19 answers)
Closed 7 years ago.
I can't find an answer to this problem, other than people asking to use an array instead. That's not what I want. I want to declare a number of variables inside a for loop with the same name except for an index number.
I=0
For int in $ints;
Do i=[$i +1]; INTF$i=$int; done
It doesn't really work. When I run the script it thinks the middle part INTF$i=$int is a command.
Without an array, you need to use the declare command:
i=0
for int in $ints; do
i=$((i +1))
declare "intf$i=$int"
done
With an array:
intf=()
for int in $ints; do
intf+=( $int )
done
Bash doesn't handle dynamic variable names nicely, but you can use an array to keep variables and results.
[/tmp]$ cat thi.sh
#!/bin/bash
ints=(data0 data1 data2)
i=0
INTF=()
for int in $ints
do
((i++))
INTF[$i]=$int
echo "set $INTF$i INTF[$i] to $int"
done
[/tmp]$ bash thi.sh
set 1 INTF[1] to data0
Related
I'm trying to read from a file, that has multiple lines, each with 3 informations I want to assign to the variables and work with.
I figured out, how to simply display them each on the terminal, but can't figure out how to actually assign them to variables.
while read i
do
for j in $i
do
echo $j
done
done < ./test.txt
test.txt:
1 2 3
a b c
So I want to read the line in the outer loop, then assign the 3 variables and then work with them, before going to the next line.
I'm guessing I have to read the values of the lines without an inside loop, but I can't figure it out right now.
Hope someone can point me in the right direction.
I think all you're looking for is to read multiple variables per line: the read command can assign words to variables by itself.
while read -r first second third; do
do_stuff_with "$first"
do_stuff_with "$second"
do_stuff_with "$third"
done < ./test.txt
The below assumes that your desired result is the set of assignments a=1, b=2, and c=3, taking the values from the first line and the keys from the second.
The easy way to do this is to read your keys and values into two separate arrays. Then you can iterate only once, referring to the items at each position within those arrays.
#!/usr/bin/env bash
case $BASH_VERSION in
''|[123].*) echo "ERROR: This script requires bash 4.0 or newer" >&2; exit 1;;
esac
input_file=${1:-test.txt}
# create an associative array in which to store your variables read from a file
declare -A vars=( )
{
read -r -a vals # read first line into array "vals"
read -r -a keys # read second line into array "keys"
for idx in "${!keys[#]}"; do # iterate over array indexes (starting at 0)
key=${keys[$idx]} # extract key at that index
val=${vals[$idx]} # extract value at that index
vars[$key]=$val # assign the value to the key inside the associative array
done
} < "$input_file"
# print for debugging
declare -p vars >&2
echo "Value of variable a is ${vars[a]}"
See:
BashFAQ #6 - How can I use variable variables (indirect variables, pointers, references) or associative arrays?
The bash-hackers page on the read builtin, documenting use of -a to read words into an array.
This question already has answers here:
bash: how does float arithmetic work?
(2 answers)
Closed 5 months ago.
I am working on bash script: need to evaluate an input and then output the result as a float *.xxx:
I do:
read var1
var2=$((var1))
#echo $var2
echo $((var1))
input: 5+50*3/20 + (19*2)/7
my output is 17 but it should be 17.929
How to evaluate it as a float?
Bash only supports integer arithmetic.
In your case, you can use bc(1).
read var1
var2="$(bc <<<"scale=2;$var1")"
Use the scale variable in bc(1) to set the number of significant digits (default with is 0).
bc(1) is subject to truncation errors (truncation happens at every step).
Another option is to use calc(1) (if it is available on your system):
var2=$(calc -d "_=config(\"display\", 3);$var1")
What I have is an array with some variables. I can iterate to get the values of those vars but what I need is actually their names (values will be used elsewhere).
Going with var[i] won't work cause I will have different names. I guess I could workaround this by creating another array with the names - something similar to this:
Getting variable values from variable names listed in array in Bash
But I'm wondering if there is a better way to do this.
var1=$'1'
var2=$'2'
var3=$'3'
Array=( $var1 $var2 $var3)
for ((i=0; i<${#Array[#]}; i++))
do
echo ${Array[i]}
done
Is:
>1
>2
>3
Should be:
>var1
>var2
>var3
It sounds like you want an associative array.
# to set values over time
declare -A Array=( ) || { echo "ERROR: Need bash 4.0 or newer" >&2; exit 1; }
Array[var1]=1
Array[var2]=2
Array[var3]=3
This can also be assigned at once:
# or as just one assignment
declare -A Array=( [var1]=1 [var2]=2 [var3]=3 )
Either way, one can iterate over the keys with "${!Array[#]}", and retrieve the value for a key with ${Array[key]}:
for var in "${!Array[#]}"; do
val="${Array[$var]}"
echo "$var -> $val"
done
...will, after either of the assignments up top, properly emit:
var1 -> 1
var2 -> 2
var3 -> 3
What about this solution?
#!/bin/bash
var1=$'1'
var2=$'2'
var3=$'3'
Array=( var1 var2 var3 )
for var in "${Array[#]}"; do
echo "$var = ${!var}"
done
The idea just consists in putting your variable names in the array, then relying on the indirection feature of Bash.
But as pointed out by #CharlesDuffy, the use of associative arrays sounds better adapted to the OP's use case.
Also, this related article may be worth reading: How can I use variable variables… or associative arrays?
I'm practicing bash and honestly, it is pretty fun. However, I'm trying to write a program that compares an array's value to a variable and if they are the same then it should print the array's value with an asterisk to the left of it.
#!/bin/bash
color[0]=red
color[1]=blue
color[2]=black
color[3]=brown
color[4]=yellow
favorite="black"
for i in {0..4};do echo ${color[$i]};
if {"$favorite"=$color[i]}; then
echo"* $color[i]"
done
output should be *black
There's few incorrect statements in your code that prevent it from doing what you ask it to. The comparison in bash is done withing square brackets, leaving space around them. You correctly use the = for string comparison, but should enclose in " the string variable. Also, while you correctly address the element array in the echo statement, you don't do so inside the comparison, where it should read ${color[$i]} as well. Same error in the asterisk print. So, here a reworked code with the fixes, but read more below.
#!/bin/bash
color[0]=red
color[1]=blue
color[2]=black
color[3]=brown
color[4]=yellow
favorite=black
for i in {0..4};do
echo ${color[$i]};
if [ "$favorite" = "${color[$i]}" ]; then
echo "* ${color[$i]}"
fi
done
While that code works now, few things that probably I like and would suggest (open to more expert input of course by the SO community): always enclose strings in ", as it makes evident it is a string variable; when looping an array, no need to use index variables; enclose variables always within ${}.
So my version of the same code would be:
#!/bin/bash
color=("red" "blue" "black" "brown" "yellow")
favorite="black"
for item in ${color[#]}; do
echo ${item}
if [ "${item}" = "${favorite}" ]; then
echo "* $item"
fi
done
And a pointer to the great Advanced Bash-Scripting Guide here: http://tldp.org/LDP/abs/html/
This question already has answers here:
Indirect variable assignment in bash
(7 answers)
Closed 6 years ago.
I have typical issue with assign into variable select statement,
I've tried many options, but none of them work..
I have function which replace column name on upper(column name).
Upper=(Column1 Column2) # Array variable
upper_function()
{
query="$1"
for ((i=0;i<${#Upper[#]};i++))
do
query=$(echo "$query" | sed -e "s/\b"${Upper[$i]}"\b/UPPER(${NAME[$i]})/g")
done
SQLQUERY="$query"
}
Below I have SQL statement:
SQLQUERY="Select column1,column2 from table"
Now, I would like to change column1 and column2 to
upper(column1) and upper(column2).
So I run function:
upper_function "$SQLQUERY"
Solution above works fine, but the case is that instead of
SQLQUERY="$query"
I would like to make my function more automatic and assigning name of Select statement into variable eg like below:
$2="$query"
and then run function:
upper_function "$SQLQUERY" "SQLQUERY"
But it is not working and I have no idea why, how to assign that variable properly? Thanks
This is, at its core, BashFAQ #6.
printf -v can be used for indirect assignments in modern (3.1+) versions of bash:
Upper=( column1 column2 ) # Array variable
upper_function() {
local colname query=$1 varname=$2
for colname in "${Upper[#]}"; do
query=$(echo "$query" | sed -e "s/\b"${colname}"\b/UPPER($colname})/g")
done
printf -v "$varname" %s "$query"
}
...thereafter:
upper_function "$SQLQUERY" SQLQUERY
On older shells, instead:
eval "$varname=\$query"
...note that you need to trust the value of $varname to not be malicious, as code injected into that variable will be run by the function. Thus, you would never want to use a filename, table name, or other potentially-attacker-controlled variable to name a variable assigned to in this way.