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")
Related
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
I have never seen the following shell script syntax:
cpu_now=($(head -n 1 /proc/stat))
cpu_sum="${cpu_now[#]:1}"
cpu_sum=$((${cpu_sum// /+}))
Can anyone explain what the ${cpu_sum// /+} mean here?
It means the same as $cpu_sum, but with all occurrences of (a space) being replaced by +. (See ยง3.5.3 "Shell Parameter Expansion" in the Bash Reference Manual.)
cpu_sum=$((${cpu_sum// /+}))
It is actually 2 step operation:
First all the spaces are being replaced by + in ${cpu_sum// /+}
Then using $((...)) arithmetic addition is being performed for adding all the numbers in $cpu_sum variable to get you aggregate sum.
Example:
# sample value of cpu_sum
cpu_sum="3222 0 7526 168868219 1025 1 357 0 0 0"
# all spaced replaced by +
echo ${cpu_sum// /+}
3222+0+7526+168868219+1025+1+357+0+0+0
# summing up al the values and getting aggregate total
echo $((${cpu_sum// /+}))
168880350
This question already has answers here:
Indirect variable assignment in bash
(7 answers)
Closed 7 years ago.
Here is the scenario:
suppose I set positional variables:
set 1 2 3 4
eval "args_$1=something"
how do I read args_1,args_2,args_3... variables
I tried
echo $args_$1
and this also not working
eval "\$$(echo arg_$1)"
How do I get value of $arg_1, to display on terminal or pass to a function, etc.
Without eval:
$ set 1 2 3 4
$ var="args_$1"
$ declare "$var=foo"
$ echo "$var"
args_1
$ echo "${!var}"
foo
This uses an indirect variable.
$ set 1 2 3 4; eval arg_$1=koba; eval echo $`echo arg_$1`
koba
PS: Using eval is not recommended.
This question already has answers here:
Variables in bash seq replacement ({1..10}) [duplicate]
(7 answers)
Brace expansion with a Bash variable - {0..$foo}
(5 answers)
Closed 8 years ago.
I'm making a program in bash that creates a histoplot, using numbers I have created. The numbers are stored as such (where the 1st number is how many words are on a line of a file, and the 2nd number is how many times this amount of words on a line comes up, in a given file.)
1 1
2 4
3 1
4 2
this should produce:
1 #
2 ####
3 #
4 ##
BUT the output I'm getting is:
1 #
2 #
3 #
4 #
however the for loop is not recognising that my variable "hashNo" is a number.
#!/bin/bash
if [ -e $f ] ; then
while read line
do
lineAmnt=${line% *}
hashNo=${line##* }
#VVVV Problem is this line here VVVV
for i in {1..$hashNo}
#This line ^^^^^^^ the {1..$hashNo}
do
hashes+="#"
done
printf "%4s" $lineAmnt
printf " $hashes\n"
hashes=""
done < $1
fi
the code works if I replace hashNo with a number (eg 4 makes 4 hashes in my output) but it needs to be able to change with each line (no all lines on a file will have the same amount of chars in them.
thanks for any help :D
A sequence expression in bash must be formed from either integers or characters, no parameter substitutions take place before hand. That's because, as per the bash doco:
The order of expansions is: brace expansion, tilde expansion, parameter, variable and arithmetic expansion and command substitution (done in a left-to-right fashion), word splitting, and pathname expansion.
In other words, brace expansion (which includes the sequence expression form) happens first.
In any case, this cries out to be done as a function so that it can be done easily from anywhere, and also made more efficient:
#!/bin/bash
hashes() {
sz=$1
while [[ $sz -ge 10 ]]; do
printf "##########"
((sz -= 10))
done
while [[ $sz -gt 0 ]]; do
printf "#"
((sz--))
done
}
echo 1 "$(hashes 1)"
echo 2 "$(hashes 4)"
echo 3 "$(hashes 1)"
echo 4 "$(hashes 2)"
which outputs, as desired:
1 #
2 ####
3 #
4 ##
The use of the first loop (doing ten hashes at a time) will almost certainly be more efficient than adding one character at a time and you can, if you wish, do a size-50 loop before that for even more efficiencies if your values can be larger.
I tried this for (( i=1; i<=$hashNo; i++ )) for the for loop, it seems to be working
Your loop should be
for ((i=0; i<hashNo; i++))
do
hashes+="#"
done
Also you can stick with your loop by the use of eval and command substitution $()
for i in $(eval echo {1..$hashNo})
do
hashes+="#"
done
This question already has answers here:
Usage of :- (colon dash) in bash
(2 answers)
Closed 9 years ago.
Sorry if this is something really simple or has already been asked, but due to the nature of the question I cannot think of any search terms to put on search engines.
Lately I have seen some bash scripts that they assign variable values like this:
$ MY_BASH_VAR=${MY_BASH_VAR:-myvalue}
$ echo "$MY_BASH_VAR"
myvalue
What is the difference from the most common way of assigning a value like this:
MY_BASH_VAR=myvalue
$ echo "$MY_BASH_VAR"
myvalue
You can look at http://linux.die.net/man/1/bash
${parameter:-word} Use Default Values. If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.
This provides a default value : MY_BASH_VAR keeps its value if defined otherwise, it takes the default "myvalue"
bruce#lorien:~$ A=42
bruce#lorien:~$ A=${A:-5}
bruce#lorien:~$ echo $A
42
Suppose the $MY_BASH_VAR was already set. In this case, it will keep the same value. If not, it will get myvalue.
case 1) $MY_BASH_VAR already set.
$ MY_BASH_VAR="hello"
$ MY_BASH_VAR=${MY_BASH_VAR:-myvalue}
$ echo "$MY_BASH_VAR"
hello
case 2) $MY_BASH_VAR not previously set.
$ MY_BASH_VAR=${MY_BASH_VAR:-myvalue}
$ echo "$MY_BASH_VAR"
myvalue
case 3) $MY_BASH_VAR set to the empty string.
$ MY_BASH_VAR=""
$ MY_BASH_VAR=${MY_BASH_VAR:-myvalue}
$ echo "$MY_BASH_VAR"
myvalue