在脚本中经常使用到变量,在bash编程中,有本地变量,局部变量、

环境变量、位置变量、特殊变量等。

本地变量的作用范围是当前shell进程。

局部变量的作用范围是当前shell的局部范围内有效。

环境变量的作用范围是当前shell及其子shell。

位置变量:为脚本引用参数用如$1表示脚本的第一个参数,$2为第二个。

特殊变量:

$0,命令本身;

$$,当前shell的PID;

$?,上个命令的返回代码;

$#,脚本共有多少个参数;

$@,把脚本的参数全部列出,分别列出;以"$1" "$2" … "$n" 的形式输出所有参数;

$*,把脚本的参数全部列出,当做一个整体列出;以"$1 $2 … $n"的形式输出所有参数;

设置变量:

set Var_name=value

显示变量:

echo ${Var_name}

取消变量:

unset Var_name

导出为环境变量:

export Var_name

shell脚本中进行算术运算:+ - * /

shell不支持浮点数,结果中的浮点数会被圆整为整数:1.23和1.99都等于1

假如:A=5,B=9,

$[$A+$B]

$(($A+$B))

let C=$A+$B

C=`expr $A + $B`,注意变量和运算符之间有空格。


在bash中最基本的结构化命令类型是if-then语句。单分支if语句如下:

if  condition

then

    commands

fi

 如果if后面的条件不成立或命令的退出状态返回值为1,then后面的命令

将不会被执行。

#!/bin/bash

file=$1

if [ -e $1 ] ; then

echo "$1 exists."

fi

 if语句可以通过对如下内容进行判断或比较,如果满足条件就执行后面的内容,不满

足则退出或其他操作。


if后面的判断条件的格式可以是以下几种:

1.test condition

2.[ expression ]

3.` expression `

4.bash命令

用法如下:

if test condition ; then

 语句1

 语句2

 ......

fi


if [ expression ]; then

 语句1

 语句2

 .....

fi


if command ; then

 语句1

 语句2

 .....

fi


1、整数比较:

 A、B为整数,注意:A、B和表示符以及[]之间有空格,否则为语法错误。

 [ A -eq B ] A等于B

 [ A -ne B ] A不等于B

 [ A -gt B ] A大于B

 [ A -lt B ] A小于B

 [ A -le B ] A小于等于B

 [ A -ge B ] A大于等于B

假如A=10 、 B=10,

 if [ $A -eq $B ]

 then

echo  "$A is equal to $B"

 fi

2、字符串比较:

注意事项:

1)、在脚本中 > < 将被理解为输出/入重定向,所以需要进行转义处理

2)、在test命令中,大写字母小于小写字母与sort命令排序相反。test使用标准的ASCII

排序。

 [ str1 = str2 ]str1等于str2

 [[ str1 == regexp ]]str1能否被regexp匹配,

 [[ str1 =~ regexp ]]同上

 [ str1 != str2 ]str1不等于str2

 [ str1 \< str2 ]str1小于str2

 [ str1 \> str2 ]str1大于str2

 [ -n str ]检查str是否为空,空为假,不空为真

 [ -z str ]检查str是否为空,空为真,不空为假

[root@www ifsh]# more iftest.sh

 #!/bin/bash

 read -p "Your name please: " Usr

 if [[ "$Usr" =~  [Rr]oot ]]

 then

   echo "hello $Usr"

 else

   echo "Who are you ?"

 fi


3、文件比较:

-f: 测试其是否为普通文件,即ls -l时文件类型为-的文件;

-d: 测试其是否为目录文件,即ls -l时文件类型为d的文件;

-e: 测试文件是否存在;存在为真,否则为假;

-r: 测试文件对当前用户来说是否可读;

-w: 测试文件对当前用户来说是否可写;

-x: 测试文件对当前用户来说是否可执行;

-s: 测试文件大小是否不空,不空则真,空则假;

-O:测试文件是否属于命令发起者;

-G:测试文件是否属于命令发起者的组;

如:如果脚本的参数是文件就cat此文件,如果是目录就ls此目录。其他类型就不处理

[root@www ifsh]# more filetest.sh

 #!/bin/bash

 file=$1

 if [ -f $1 ] ; then

  cat $1

  elif [ -d $1 ];then

  ls $1

 else

  echo "$1 is unknown."

 fi

其他测试条件:

1)组合条件测试,连接多个条件,

-a 与

-o 或

! 非


&& 与

|| 或

! 非

[root@www ifsh]# more ifand.sh

 #!/bin/bash

 read -p "Your score: " N

if  [ $N -ge 80 -a $N -le 90 ] ; then

   echo "Level B"

elif [ $N -gt 90 ] && [ $N -le 100 ]  ; then

   echo "Level A"

else

 echo "Level C"

fi

2)检查文件日期:

-nt 比较一个文件是否比另一个文件新。

-ot 比较一个文件是否比另一个文件旧。

[root@www ifsh]# more testnt.sh

 #!/bin/bash

 file1=/tmp/a

 file2=/tmp/b

if [ $file1 -nt $file2 ];then

 echo "$file1 is newer"

else

 echo "$file2 is newer"

fi

多分支if语句:

语法格式:

if 条件1; then

 语句1

 语句2

 ...

elif 条件2; then

 语句1

 语句2

 ...

elif 条件3; then

 语句1

 语句2

 ...

else

 语句1

 语句2

 ...

fi

例如:给出一个用户,根据其Uid判断属于哪一类用户。

#!/bin/bash

read -p "Please chose a username: " USR

if id $USR &> /dev/null; then

    Uid=`grep -w "^$USR" /etc/passwd | cut -d: -f3`

 if [ $Uid -eq 0 ] ; then

    echo "$USR is here"

 elif [ $Uid -gt 499 ] ; then

    echo "$USR is a common user."

 else

    echo "$USR is a SystemUser."

 fi

fi


 在脚本中,可以获取上条命令的执行状态值,正常执行为0,非正常为1-255之间的数值

用户可以自定义命令返回值。

例子:根据用户shell的结束符是否为sh来判定其是否为登录用户:

 #!/bin/bash

 Shell=`grep "^$1:" /etc/passwd | cut -d: -f7`

 if [ -z $Shell ]; then

   echo "No shell."

   exit 3

 fi

 if [[ "$Shell" =~ sh$ ]]; then

     echo "Login User."

     Ret=0

else

    echo "None Login User."

    Ret=4

fi

 exit $Ret

for循环

事先提供一个元素列表,而后使用变量去遍历此列表;每访问一个元素,就执行一次循

环体,直到元素访问完毕。

for Var_name in 元素1 元素2....;do

语句1

语句2

......

done

元素列表的生成方法有

1、逐个给出;{n1..n2}表示序列

如:#!/bin/bash

for I in 1 2 3 4 5; do

let sum+=$I

done ;

  echo $sum

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

#!/bin/bash

for I in {1..5}; do

 let sum+=$I

done

 echo $sum (效果跟上面的一样)

2、使用通配符实现文件通配,如:查看/var下文件的类型

#!/bin/bash

for file in /var/* ; do

 file $file

done

3、使用命令生成列表:

#!/bin/bash

for I in `seq 1 100`;do

 let sum+=$I

done

 echo $sum

seq命令:

seq 1 100 输出1到100,

seq 1 2 100 输出1 3 5 7 9 ...99 就是输出从1开始步长为2(间隔为2)直到100


比较经典的一个用法就是计算1到100的和:

计算100以内奇数和偶数的和:

 #!/bin/bash

 Sum=0

 Sum2=0

for I in {1..100}; do

    if [ $[$I%2] -eq 0 ];then

          Sum=$[$Sum+$I]

   else

         Sum2=$[$Sum2+$I]

   fi

done

 echo "偶数和是 $Sum"

 echo "奇数和是 $Sum2"

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

 #!/bin/bash

 let sum=0

for I in $(seq 0 2 100); do

   sum=$[$sum+$I]

done

echo "偶数的和是:$sum"

for X in $(seq 1 2 100); do

  sum2=$[$sum2+$X]

done

 echo "奇数的和是: $sum2"

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

添加用户,如果存在就显示存在,不存在就创建

 [root@www forsh]# more adduser.sh

 #!/bin/bash

for I in {1..10}; do

    if id user$I &> /dev/null ; then

      echo "user$I exist."

    else

      useradd user$I

      echo "user$I" | passwd --stdin user$I &> /dev/null

      let Count++

      echo "user$I added."

    fi

done

 echo  "$Count new comers."


脚本练习题:

1、显示/etc/passwd文件中第1、3、6、12个用户的用户名、ID和shell;

[root@www forsh]# more id.sh

#!/bin/bash


for I in 1 3 6 12 ; do

  Uname=`head -$I /etc/passwd | tail -1 | cut -d: -f1`

  Uid=`head -$I /etc/passwd |tail -1 | cut -d: -f3`

  Gid=`head -$I /etc/passwd | tail -1 | cut -d: -f4`

  BaseGrp=`cat /etc/group | grep -w  "$Gid" | cut -d: -f1`

if [ $I -eq 1 ] ; then

  echo -e "\tThe ${I}st username:$Uname UID:$Uid Group:$BaseGrp"

elif [ $I -eq 3 ]; then

  echo -e "\tThe ${I}rd Username:$Uname UID:$Uid Group:$BaseGrp"

else

  echo -e "\tThe ${I}th Username:$Uname UID:$Uid Group:$BaseGrp"

fi

done

显示效果为:

The 1st username:root UID:0 Group:root

The 3rd Username:daemon UID:2 Group:daemon

The 6th Username:sync UID:5 Group:root

The 12th Username:operator UID:11 Group:root

知识点:

shift 弹出参数

[root@www forsh]# more t1.sh

 #!/bin/bash

 echo $1

 shift 4

 echo $1

 shift

 echo $1

[root@www forsh]# ./t1.sh 1 2 3 4 5 6 7

1

5

6

给出任意个任意长度的数,计算这几个数的和。

[root@www forsh]# more ta.sh

 #!/bin/bash

 let sum=0

for I in `echo $*`;do

  let sum=$sum+$1

  shift

done

echo "$sum"