linux bash算术运算和条件语句
+, -, *(乘), /(除), **(乘方), %(取模)
let var=算术运算符表达式
高级let用法:let i+=2
+=,-=,*=,/=,%=,**=
自增:let var++
var=$[算术运算符表达式]
var=$((算术运算符表达式))
var=$(expr $ARG1 OP $APG2)
</font color=red>注意:乘法符号在某些场景中需要使用转义符
练习1:写一个脚本文件,完成如下功能:添加3个用户,求这3个用户的UID之和。
#!/bin/bashid testUser1 > /dev/null || useradd testUser1id testUser2 > /dev/null || useradd testUser2id testUser3 > /dev/null || useradd testUser3uid1=`grep "testUser1" /etc/passwd | cut -d: -f3`uid2=`grep "testUser2" /etc/passwd | cut -d: -f3`uid3=$(grep "testUser3" /etc/passwd | cut -d: -f3)#方法1#let num=$uid1+$uid2+$uid3#方法2#num=$[$uid1+$uid2+$uid3]#方法3num=$(($uid1+$uid2+$uid3))#方法4#num=$(expr $uid1 + $uid2 + $uid3)echo $num
练习2:写一个脚本文件,完成如下功能:求/etc/passwd文件中第10行和第20行的用户的UID之和
#!/bin/bash#先用head取前10行,再用tail取最好一行,然后再用cut切la=`head -10 /etc/passwd | tail -1 | cut -d: -f3`lb=`head -20 /etc/passwd | tail -1 | cut -d: -f3`echo $laecho $lblet lc=$la+$lbecho $lc
练习3:写一个脚本文件,完成如下功能:求/etc/passwd文件中,uid最大的2个uid之和
#!/bin/bash#先用冒号把文件分成多列,用第三列从大到小排序后,分别取第一行和第二行,最后在用cut切开la=`sort -t: -k3 -nr /etc/passwd | head -1 | cut -d: -f3`lb=`sort -t: -k3 -nr /etc/passwd | head -2 | tail -1 | cut -d: -f3`echo $laecho $lblet lc=$la+lbecho $lc
练习4:写一个脚本文件,完成如下功能:通知2个文件里的空白行数之和
#!/bin/bash#用grep找出空白行(使用正则表达式),然后再用wc数一数有多少行la=`grep -e "^[[:space:]]*$" /etc/rc.d/init.d/functions | wc -l`lb=`grep -e "^[[:space:]]*$" /etc/inittab | wc -l`echo $laecho $lblet lc=$la+$lbecho $lc
条件语句
测试表达式:
test expression
[ expression ]
[[ expression ]]
注意:中括号中间的空格,没有空格就是语法错误
bash的条件测试类型
数值比较大小
例子:[ 2 -ne 3 ]和test 2 -ne 3效果一样
#!/bin/bashif [ 2 -ne 3 ]; then echo 11else echo 22fiif test 2 -ne 3; then echo 111else echo 222fi
-eq:等于 [ $num1 -eq $num2 ]
-ne:不等于[ $num1 -ne $num2 ]
-gt:大于[ $num1 -gt $num2 ]
-ge:大于等于[ $num1 -ge $num2 ]
-lt:小于[ $num1 -lt $num2 ]
-le:小于等于[ $num1 -le $num2 ]
字符串比较
== :等于
> :大于
< :小于
!= :不等于
=~ :左侧字符串是否被右侧的正则表达式所匹配。
-z "STRING" :指定字符串为空则为真
-n "STRING":指定字符串不为空则为真
做字符串比较的变量,最好加上“”。不加的话,如果做比较的某个变量没有被定义的话,执行就会出错。
下面的例子,tom是不存在的变量,不加括号就出错误了,加了就没有错误。
$ [ tom = $tom ]-bash: [: tom: unary operator expected$ [ tom = "$tom" ]$ echo $?1
字符串比较,最好要用[[]]。
下面的例子,说明了用[]无法比较
$ [ a > b ]$ echo $?0$ [ a < b ]$ echo $?0$ [ "a" < "b" ]$ echo $?0$ [ "a" > "b" ]$ echo $?0
下面的例子,说明用[[ ]]达到了预期。
$ [[ a < b ]]$ echo $?0$ [[ a > b ]]$ echo $?1$ [[ "a" > "b" ]]$ echo $?1$ [[ "a" < "b" ]]$ echo $?0
字符串空的判断:
$ [[ -z "$tom" ]]$ echo $?1[ys@localhost ~]$ [[ -n "$tom" ]][ys@localhost ~]$ echo $?
正则表达式的匹配:
$ tom=ooo[ys@localhost ~]$ [[ $tom =~ o.* ]][ys@localhost ~]$ echo $?0[ys@localhost ~]$ tom=jerry[ys@localhost ~]$ [[ $tom =~ o.* ]][ys@localhost ~]$ echo $?1
文件测试
文件存在性检查:-a FILE,或者,-e FILE。存在返回0.
例子:
[ -a /etc/passwd ]
,[ -e /etc/passwd ]
文件存在性和类型检查
-b FILE:文件存在,且类型是块设备,则返回0.
-c FILE:文件存在,且类型是字符设备,则返回0.
-d FILE:文件存在,且类型是目录,则返回0.
-f FILE:文件存在,且类型是普通文件,则返回0.
-h或 -L FILE:文件存在,且类型是符号链接,则返回0.
-p FILE:文件存在,且类型是命名管道,则返回0.
-S FILE:文件存在,且类型是本地套接字,则返回0.
$ [ -b /dev/sda ][ys@localhost scripts]$ echo $?0[ys@localhost scripts]$ [ -b /dev/sdad ][ys@localhost scripts]$ echo $?1[ys@localhost scripts]$ [ -b 2.sh ][ys@localhost scripts]$ echo $?1
文件权限检查
-r FILE:文件存在,且当前用户(运行此shell进程的用户)可读,则返回0.
-w FILE:文件存在,且当前用户(运行此shell进程的用户)可写,则返回0.
-x FILE:文件存在,且当前用户(运行此shell进程的用户)可执行,则返回0.
特殊权限检查
-u FILE:文件存在,且拥有suid权限,则返回0.
-g FILE:文件存在,且拥有sgid权限,则返回0.
-k FILE:文件存在,且拥有sticky权限,则返回0.
文件是否有内容
-s FILE:文件存在,且有内容,则返回0
时间戳
-N FILE:文件自从上一次读取操作后,是否被修改过。
从属关系
-O FILE:当前用户是否文件属主
-G FILE:当前用户是否在文件属组里。
双目
FILE1 -ef FILE2:如果FILE1和FILE2是指向同一个文件系统的相同inode的硬链接,则返回0.
FILE1 -nt FILE2:如果FILE1的修改时间戳新于FILE,则返回0
FILE 1 -ot FILE2:如果FILE1的修改时间戳旧于FILE,则返回0
组合测试条件
第一种方式:
[ expression1 ] && [ expression2 ]
[ expression1 ] || [ expression2 ]
! COMMOND
第二种方式:
与运算:[ expression1 -a expression2 ]
或运算:[ expression1 -o expression2 ]
练习:判断主机名称是否为空,或者是否是localhost.localdomain
#!/bin/bashhostname=`hostname`if [ -z "$hostname" -o "$hostname" == "localhost.localdomain" ]; then hostname=11111else echo "ng"fiecho $hostname
向脚本文件传递执行时候的参数
使用位置参数变量:$1,$2,...${10},${11}.
10之后的参数必须加上{}。
$0:是脚本本身的路径加脚本文件的名字。
$#:是参数的个数
$*:拿到所有参数。但把所有参数汇总成了一个串
$@:拿到所有参数。但没有把参数汇总成一个串。
当执行下面命令后,$1的值就是111;$2的值就是222;$3的值就是333;
$ ./script.sh 111 222 333
shift用法:shift n:踢掉前n个位置参数变量
下面的内容保存在shift.sh中
#!/bin/bashecho $1 $2shift 1echo $1shift 1echo $1
执行shift.sh的结果:
# bash shift.sh 111 222 333111 222222333
练习:传递2个文本文件的路径给脚本,计算出空白行数之和。
#!/bin/bashla=`grep -e "^[[:space:]]*$" $1 | wc -l`lb=`grep -e "^[[:space:]]*$" $2 | wc -l`echo $laecho $lblet lc=$la+$lbecho $lc
执行结果:
# bash sumforarg.sh /etc/rc.d/init.d/functions /etc/inittab91091
if语法
if con1 ; thenelif con2 ; thenelsefi
练习:查看给定用户是否存在,不存在则创建此用户。
#!/bin/bashif ! grep "^$1\>" /etc/passwd &> /dev/null ; then useradd $1 # 设定用户$1的密码是111 echo "111" | passwd --stdin $1 &> /dev/null echo "add user $1 donw!"fi
练习:比较2个数字的大小
#!/bin/bash#声明一个变量,是整数。declare -i max#参数个数小于2if [ $# -lt 2 ]; then echo "at least one argu" exit 1fi#参数1大于参数2if [ $1 -ge $2 ]; then max=$1else max=$2fiecho "max number is $max"
练习:判断给定用户名的id号是奇数还是偶数
#!/bin/bashif [ $# -lt 1 ]; then echo "at least one argu" exit 1fi#取得用户的iduid=$(grep "^$1\>" /etc/passwd | cut -d: -f3)echo $uid#判断奇偶数if [ $[$uid % 2] -eq 0 ]; then echo "oushu"else echo "jishu"fi
运行结果:
# bash jigou.sh ys1000oushu# bash jigou.sh fedora1005jishu
练习:给2个文本文件路径,如果文件不存在,则结束脚本;都存在则返回每个文件的行数,并找出行数多的文件
#!/bin/bashif [ $# -lt 2 ]; then echo "at least two argu" exit 1fiif ! [ -e $1 -a -e $2 ]; then exit 1else la=`wc -l < $1` lb=`wc -l < $2` echo "$1 行数:$la;$2 行数:$lb" if [ $la -ge $lb ]; then echo "$1 行数多" else echo "$2 行数多" fifi
运行结果:
# bash sum1.sh /etc/passwd /etc/fstab/etc/passwd 行数:56;/etc/fstab 行数:13/etc/passwd 行数多
case语法
case $var in pat1) ;; pat2) ;; pat3) ;; *) ;;esac
pat支持globbing风格:
*:匹配任意长度的任意字符
?:匹配任意单个字符
[]:匹配指定范围内的任意单个字符
[^]:匹配指定范围外的任意单个字符
{}:表示符合括号内包含的多个文件
aaa|bbb:aaa或bbb
执行完脚本文件后,返回值是啥?
默认是脚本文件里最后一条命令的返回值。
可以自定义返回值:使用exit n
命令,n为数字。
当shell进程遇到exit命令时,进程会立即终止,因此exit后面的命令就不执行了。