可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm quite new to bash scripting and usually avoid it all costs but I need to write a bash script to execute some simple things on a remote cluster. I'm having problems with a for loop that does the following:
for i in {1..20}
do
for j in {1..20}
do
echo (i*i + j*j ) **.5 <--- Pseudo code!
done
done
Can you help me with this simple math? I've thrown $
's everywhere and can't write it properly. If you could help me understand how variables are named/assigned in bash for loops and the limitations of bash math interpretation (how do you do the square root?) I'd be very grateful. Thanks!
回答1:
Here's a decent solution:
for i in {1..20}
do
for j in {1..20}
do
echo "scale = 3; sqrt($i*$i + $j*$j)" | bc
done
done
Output will be:
1.414
2.236
3.162
2.236
[...etc...]
回答2:
Arithmetic expansion needs $((...))
notation, so something like:
echo $((i*i + j*j))
However, bash only uses integers so you may need to use an external tool such as dc.
E.g.
dc -e "18k $i $i * $j $j * + v p"
回答3:
Shell math can be done in several ways.
echo $(( i*i + j*j ))
echo $[ i*i + j*j ]
expr "$i" '*' "$i" '+' "$j" '*' "$j"
However, this can only handle integer arithmetic. Instead, you can use bc
:
echo "scale = 5; sqrt( $i*$i + $j*$j)" | bc
Change scale
to the number of decimal places desired.
回答4:
#!/bin/bash
for i in {1..20}; do
for j in {1..20}; do
echo 5k$i $i\* $j $j\*+vp | dc
done
done
回答5:
Use double paren to evaluate a variable.
variableA=$((variableB*variableC))
Only for ints though.
回答6:
does your remote cluster only have bash? if not, try and see if you have awk
awk 'BEGIN{
for(i=1;i<=20;i++){
for(j=1;j<=20;j++){
print ( i*i + j*j ) ** 0.5
}
}
}'
回答7:
Typically you would use $((1*3)), but your case won't work as bash doesn't support floating point numbers. You'll have to use an external tool like awk, bc or dc:
http://mywiki.wooledge.org/BashFAQ/022
回答8:
The code
echo $[(($i * $i) + ($j * $j)) ** $X]
will work if $X
is an integer. You're trying to take the square root, and I'm not sure if bash's built-in arithmetic will do that. You'll probably be better off using a more powerful calculator tool (like bc
, et al.) for this.
回答9:
Bash doesn't offer mathematical functions. However, you almost certainly have the korn shell installed. This should work:
#!/bin/ksh
for i in {1..20}
do
for j in {1..20}
do
x=$((sqrt(i*i + j*j)))
echo "sqrt($i^2 + $j^2) = $x"
done
done
The beginning of the output is
sqrt(1^2 + 1^2) = 1.41421356237309505
sqrt(1^2 + 2^2) = 2.2360679774997897
sqrt(1^2 + 3^2) = 3.16227766016837933
sqrt(1^2 + 4^2) = 4.12310562561766055
sqrt(1^2 + 5^2) = 5.09901951359278483
sqrt(1^2 + 6^2) = 6.08276253029821969
sqrt(1^2 + 7^2) = 7.07106781186547524
sqrt(1^2 + 8^2) = 8.06225774829854965
sqrt(1^2 + 9^2) = 9.05538513813741663
sqrt(1^2 + 10^2) = 10.0498756211208903
回答10:
with zsh, this will work
for i in {1..20};do
for j in {1..20};do
echo $((($i*$i + $j*$j)**.5))
done
done
回答11:
Another form of integer math expressions in Bash puts the double parentheses on the outside of the entire expression for assignment operations:
(( var = i ** 2 ))
(( i++ ))
(( position += delta ))
As you can see, dollar signs are not needed here (nor inside $(())
). Also, spaces are permitted around the equal sign.
Also, this form can be used in conditionals:
sixpacks=8 # note spaces not allowed here
(( beerprice = 8 )) # but you can use spaces this way
budget=50
# you can do assignments inside a conditional just like C
until (( (( beertotal = sixpacks * beerprice )) <= budget ))
do
(( sixpacks-- ))
done
echo "Buy ${sixpacks} six-packs at \$${beerprice} each for a total of \$${beertotal}."
Or you can replace all that with this, of course:
beerprice=8
budget=50
# integer division
(( sixpacks = budget / beerprice ))
(( beertotal = sixpacks * beerprice ))
echo "Buy ${sixpacks} six-packs at \$${beerprice} each for a total of \$${beertotal}."
Bash also has a let
statement:
let a=2**16
let 'a>>=1' # bitwise shift - some operations need to be quoted or escaped
(( a>>=1 )) # but not inside (())