bash中变量与运算
2013-04-04 23:28:13 阿炯

1、变量替换
2、算术运算
3、逻辑判断
4、运算符大盘点


1、变量替换

Bash Shell可以进行变量的条件替换,既只有某种条件发生时才进行替换,替换条件放在{}中。
(1) ${value:-word}
当变量未定义或者值为空时,返回值为word的内容,否则返回变量的值。

(2) ${value:=word}
与前者类似,只是若变量未定义或者值为空时,在返回word的值的同时将word赋值给value。

(3) ${value:?message}
若变量以赋值的话,正常替换;否则将消息message送到标准错误输出(若此替换出现在Shell程序中,那么该程序将终止运行)。

(4) ${value:+word}
若变量以赋值的话,其值才用word替换,否则不进行任何替换。

(5) ${value:offset}
${value:offset:length}从变量中提取子串,这里offset和length可以是算术表达式。

(6) ${#value}
变量的字符个数(变量的字符个数,并不是变量个数)

(7) ${value#pattern}
${value##pattern}去掉value中与pattern相匹配的部分,条件是value的开头与pattern相匹配。#与##的区别在于一个是最短匹配模式,一个是最长匹配模式。

(8) ${value%pattern}
${value%%pattern}于(7)类似,只是是从value的尾部于pattern相匹配,%与%%的区别与#与##一样。

(9) ${value/pattern/string}
${value//pattern/string}进行变量内容的替换,把与pattern匹配的部分替换为string的内容,/与//的区别与上同。
 
注意:上述条件变量替换中,除(2)外其余均不影响变量本身的值。感觉它对变量的控制还是挺复杂的,不是那么好理解。
 
2、算术运算
在Bash Shell中,只能进行两个整数间的运算,其结果仍为整数。要进行算术运算,需要使用let命令,语法为:
let expr
 
expr是一个包含项和操作符的表达式,项可以是一个变量或是一个整数常数,当使用整数常数时,其默认为十进制整数,用户可以用radio#number来指定其它形式的整数,其中radio定义了整数是几进制表示的,number是该整数的值;若radio>10,那么数字字符可从0-9和A-Z。

在表达式中支持的操作符及其含义为:
 +,-,*,/,% : 加,减,乘,除,取模
 >>,<<,&,^,| : 左移,右移,位与,位异或,位或
 ?: : 三元运算符.与Perl语言中的定义一致
 ~ : 取补码
 !,>=,<=,>,<,==,!=,&&,|| : 比较运算
 =,+=,-=,*=,/=,%=,<<=,>>=,&=,^=,|= : 数字的各种运算
表达式式中也可以使用括号,括号或运算优先级的定义与一般计算机语言中的相同。

let命令具有返回值.当计算结果(若有多个表达式时,以最后一个为准)为0时,返回值为1,否则为0.

当表达式中含有shell的特殊字符(如|)时,需要用引用符('或")将其引用起来,使用let时还需要注意:对于let x+y这样的式子,shell虽然计算了x+y的值,但却将结果丢弃;若不想这样,可以使用let sum=x+y将x+y的结果保存在变量sum中,另外还可以使用((和))操作符取代let命令,而且这样的话,还可以省去对算术表达式的引用,如果想返回表达式的值,则需用$(())的格式。
 
在条件判断时:'='用于比较字符串,而'-eq'用于比较整型数。

数学运算再看
Math and Arithmetic

x=3; y=$((x+2)); echo $y
5

与C语言一样,要注意数字的空间范围,防止溢出。

Bash Arithmetic Operators
Arithmetic OperatorDescription
id++, id–variable post-increment, post-decrement
++id, –idvariable pre-increment, pre-decrement
-, +unary minus, plus
!, ~logical and bitwise negation
**exponentiation
*, /, %multiplication, division, remainder (modulo)
+, -addition, subtraction
«, »left and right bitwise shifts
<=, >=, <, >comparison
==, !=equality, inequality
&bitwise AND
^bitwise XOR
|bitwise OR
&&logical AND
||logical OR
expression ? expression : expressionconditional operator
=, *=, /=, %=, +=, -=, «=, »=, &=, ^=, |=assignment



expr

$ expr 1 + 1
2

$ myvar=$(expr 1 + 1)
$ echo $myvar
2

$ echo "$((20+5/2))"
22

expr $myvar \* 3
6

shell builtin commands
let or declare printf


let myvar+=1 ; echo $myvar
7
$ let myvar+1 ; echo $myvar
8
$ let myvar2=myvar+1 ; echo $myvar2
9

$ declare -i x=4 y=5 z=x*y u=z/2
$ echo $x $y $z $u
4 5 20 10

$ declare -i myvar3=myvar2*2 ; echo $myvar3
18
$ echo $myvar3 ; myvar3="none"; echo $myvar3
18
0

printf <precision> 即能处理小数(一些shell能直接支持简单的小数运算)

printf %.<precision>f "$((10**<multiplier> * 2/3))e-<multiplier>

$ printf %.3f "$((10**3 * 2/3))e-3"
0.666
$ printf %.1f "$((10**3 * 2/3))e-3"
0.7


Bash Arithmetic Expansion

$((...))
$(( arithmetic expression ))

$ myvar=3 && echo $myvar
3
$ echo $((myvar+2))
5
$ myvar=$((myvar+3))
$ echo $myvar
6
$ ((myvar+=3))
$ echo $myvar
9

$ ((x=4,y=5,z=x*y,u=z/2)) ; echo $x $y $z $u
4 5 20 10


还可以调用awk、bc命令来实现,还有人在stackexchange进行了简单的总结

$ printf %.10f\\n "$((10**9 * 20/7))e-9"   # many shells. Not mksh.
$ echo "$((20.0/7))"                       # (ksh93/zsh/yash, some bash)
$ awk "BEGIN {print (20+5)/2}"
$ zcalc
$ bc <<< 20+5/2
$ bc <<< "scale=4; (20+5)/2"
$ dc <<< "4 k 20 5 + 2 / p"
$ expr 20 + 5
$ calc 2 + 4
$ node -pe 20+5/2  # Uses the power of JavaScript, e.g. : node -pe 20+5/Math.PI
$ echo 20 5 2 / + p | dc
$ echo 4 k 20 5 2 / + p | dc
$ perl -E "say 20+5/2"
$ python -c "print(20+5/2)"
$ python -c "print(20+5/2.0)"
$ clisp -x "(+ 2 2)"
$ lua -e "print(20+5/2)"
$ php -r 'echo 20+5/2;'
$ ruby -e 'p 20+5/2'
$ ruby -e 'p 20+5/2.0'
$ guile -c '(display (+ 20 (/ 5 2)))'
$ guile -c '(display (+ 20 (/ 5 2.0)))'
$ slsh -e 'printf("%f",20+5/2)'
$ slsh -e 'printf("%f",20+5/2.0)'
$ tclsh <<< 'puts [expr 20+5/2]'
$ tclsh <<< 'puts [expr 20+5/2.0]'
$ sqlite3 <<< 'select 20+5/2;'
$ sqlite3 <<< 'select 20+5/2.0;'
$ echo 'select 1 + 1;' | sqlite3
$ psql -tAc 'select 1+1'
$ R -q -e 'print(sd(rnorm(1000)))'
$ r -e 'cat(pi^2, "\n")'
$ r -e 'print(sum(1:100))'
$ smjs
$ jspl
$ gs -q  <<< "5 2 div 20 add  ="


3、逻辑判断
命令判断会用到三个特殊符号分号(;),&&,||

(1).分号(;)
不考虑命令的相关性,连续执行,不保证命令全部执行成功。
# ls xxxx ; echo freeoa
ls: 无法访问xxxx: 没有那个文件或目录
freeoa

(2).&&
逻辑与,只有在前面的命令执行成功时,才会执行后面的命令
# ls /opt
rh
# cd /opt/ && touch a && ls
a  rh

逻辑与经常用于源码编译:./configure && make -j 3 && make install

(3).||
逻辑或,如果前面的命令执行成功,那么后面的命令就不执行;如果前面的命令执行不成功,才会执行后面的命令。
# ls a || cd /mnt
a
# ls xxx || cd /mnt
ls: 无法访问xxx: 没有那个文件或目录
# pwd
/mnt

(4).综合使用
Linux执行命令是从左往右执行,从上往下执行。
# cd /root/newDir || mkdir /root/newDir && touch /root/newDir/freeoa.tar && ls /root/newDir
bash: cd: /root/newDir: 没有那个文件或目录
freeoa.tar


4、运算符大盘点

常见的bash运算符组包括算术运算符、比较运算符、位运算符、逻辑运算符、字符串运算符和文件运算符。

--------------------------------
数字的加减乘除

'+'、'+='
$ echo `expr 5 + 25`

$ n=20
$ echo $((n += 30))

'-'、'-='
$ echo `expr 35 - 15`
$ n=120
$ echo $((n -= 100))

'*'、'*='、'**'
$ echo $((5 * 7))
$ n=10
$ echo $((n * 50))
$ echo $((5 ** 3))

'/'、'/='
$ let n=30/6
$ echo $n

$ n=50
$ let n=n/10
$ echo $n

'%'、'%='
$ echo `expr 89 % 5`
$ n=150
$ echo `expr $n %= 7`

%=好像没有实践成功。

自增与自减
各自其中有两种情况,如自增中就分前增(Pre)与后增(Post)。
$ i=39
$ echo $((++i+10))

$ i=10
$ echo $((i++))
$ echo $i

$ i=36
$ echo $((--i+15))

$ i=6
$ echo $((i--))
$ echo $i

--------------------------------
逻辑运算(Logical Operator):&&、||、!

'&&':Boolean AND logic.
if [[ $1 = "fahmida" && $2 = "abcd" ]]
then
  echo "Valid user"
else
  echo "Invalid user"
fi

'||' :Boolean OR logic.
if [[ $1 = 101 || $1 = 780 ]]
then
  echo "You have won the ticket"
else
  echo "Try again"
fi

'!' :Boolean logical NOT.
terminate=$1
if [[ !$terminate  ]]
then
  echo "Program is running"
else
  echo "Program is terminated"
fi

----------------
三元运算(Ternary Operator):?:
let n=20,v1=100,v2=200
echo $(( n>=20 ? v1 : v2 ))

----------------
",(comma)"运算符
用于在一行中执行多个语句。以下命令显示了此运算符的使用,将$n的值分配给10,30与$n相加,然后打印$n的数值。
echo "$(( n=10, n=n+30 ))"

--------------------------------
(二进制)位运算符(Bitwise Operator)
&,&=、|,|=、^,^=、~

& Bitwise Operator
'&' operator is bitwise AND operation.
$ echo $((3 & 6))

&= Bitwise Operator
'&=' 用于对变量的值执行逐位AND运算,并将结果存储在变量中。运行以下命令以显示此运算符的使用。
$ var=3
$ ((var&=7))
$ echo $var

| Bit-wise Operator
'|' operator is used to perform bit-wise OR operation.
$ echo $((3 | 6))

|= Bitwise Operator
'|=' operator used is to perform bitwise OR operation.
$ var=4
$ ((var|=2))
$ echo $var


^ Bitwise Operator
'^' operator is used to perform bitwise XOR operation.
$ echo $((3 ^ 6))


^= Bitwise Operator
'^=' operator is used to perform bitwise XOR operation.
$ var=5
$ ((var^=2))
$ echo $var


~ Bitwise Operator
'~' operator is used to complement the value. The complement of 7 is -8.
$ echo $(( ~7 ))


<< Bitwise Operator
'<<' operator is used to left-shift the binary value.
$ echo $(( 6<<1 ))


<<= Bitwise Operator
'<<=' operator is used to left shift the binary value of any variable and store the value in that variable.
$ var=5
$ ((var <<= 1))
$ echo $var


>> Bitwise Operator
'>>' operator is used to right-shift the binary value.
$ echo $(( 8>>1 ))

>>= Bitwise Operator
'>>=' operator is used to right-shift the binary value of any variable and store the value in that variable.
$ var=7
$ ((var >>= 1))
$ echo $var

----------------
模板字符段
<<< here-string Operator
'<<<' operator is used to passing the data from the right side to standard input.
$ cat <<< "Linux Hint"

--------------------------------
数字比较(Integer operator)

-eq
'-eq' operator is used to check two values are equal or not.
n=50
if [ $n -eq 80 ]
then
  echo "The number is equal to 80"
else
  echo "The number is not equal to 80"
fi


-ne
'-ne' operator is used to check two numbers are not equal or equal.
n=50
if [ $n -ne 100 ]
then
  echo "The number is not equal to 100"
else
  echo "The number is equal to 100"
fi


-gt
'-gt' operator is used to compare two numbers and it returns true if any number is greater than the other number.
n=50
if [ $n -gt 50 ]
then
  echo "The number is greater than 50 "
else
  echo "The number is less than or equal to 50"
fi


-ge
'-ge' operator is used to compare two numbers and it returns true if any number is greater than or equal to the other number.
n=50
if [ $n -ge 50 ]
then
  echo "The number is greater than or equal to 50"
else
  echo "The number is less than 50"
fi


-lt
'-lt' operator is used to compare two numbers and it returns true if any number is less than the other number.
n=50
if [ $n -lt 50 ]
then
  echo "The number is less than 50"
else
  echo "The number is greater than or equal to 50"
fi


-le
'-le' operator is used to compare two numbers and it returns true if any number is less than or equal to the other number.
n=50
if [ $n -le 50 ]
then
  echo "The number is less than or equal to 50"
else
  echo "The number is greater than 50"
fi


<
'<' operator is used to compare two numbers and it returns true if any number is less than the other number.
n=50
if [[ $n < 50 ]]
then
  echo "The number is less than 50"
else
  echo "The number is greater than or equal to 50"
fi


<=
'<=' operator is used to compare two numbers and it returns true if any number is less than or equal to the other number.
n=55
if (( $n <= 50 ))
then
  echo "The number is less than or equal to 50"
else
  echo "The number is greater than 50"
fi


>
'>' operator is used to compare two numbers and it returns true if any number is greater than the other number.
n=55
if (( $n > 50 ))
then
  echo "The number is greater than 50"
else
  echo "The number is less than or equal to 50"
fi


>=
'>=' operator is used to compare two numbers and it returns true if any number is greater than or equal to the other number.
n=55
if (( $n >= 55 ))
then
  echo "The number is greater than or equal to 55"
else
  echo "The number is less than 55"
fi

--------------------------------
字符(串)比较(String Operator)

=
'=' operator is used to compare the equality of two string values.
str="Mango"
if [ $str = "Orange" ]
then
  echo "The value are equal"
else
  echo "The value are not equal"
fi


== Equality
'==' operator is used to compare the equality of two values.
var=100
if [ $var == 100 ]
then
  echo "The value is equal to 100"
else
  echo "The value is not equal to 100"
fi


!= Inequality
'!=' operator is used to comparing the inequality of two values.
var=50
if [ $var != 100 ]
then
  echo "The value is not equal to 100"
else
  echo "The value is equal to 100"
fi


<
'<' operator is used to compare two string values and it returns true if the first value is less than second value.
str1="Mango"
str2="Orange"
if [[ $str < $str2 ]]
then
  echo "$str1 is lower than $str2"
else
  echo "$str1 is greater than $str2"
fi


>
'>' operator is used to compare two string values and it returns true if the first value is greater than the second value.
str1="Mango"
str2="Orange"
if [[ $str > $str2 ]]
then
  echo "$str1 is greater than $str2"
else
  echo "$str2 is greater than $str1"
fi


-z string
'-z' operator is used to check the length of a string is zero or not.
str=""
if [ -z $str ]
then
  echo "The string length is zero"
else
  echo "The string length is more than zero"
fi


-n string
'-n' operator is used to check the length of a string is non-zero or not.
str="Linux"
if [ -n $str ]
then
  echo "The string length is non-zero"
else
  echo "The string length is zero"
fi

--------------------------------
逻辑运算(logical operator)

-a
'-a' operator is used to create Boolean AND logic within two or more conditions.
let n1=25,n2=65
if [ $n1 -gt 24 -a $n2 -lt 66 ]
then
  echo "You are eligible"
else
  echo "You are not eligible"
fi


-o
'-o' operator is used to create Boolean OR logic within two or more conditions.
let score1=55,score2=75
if [ $score1 -eq 55 -o $score2 -eq 80 ]
then
  echo "You have passed"
else
  echo "You have failed"
fi

--------------------------------