脚本编程中的面向过程:顺序执行,选择执行,循环执行。在谈shell脚本之前我们来认识几个bash的特殊变量,并了解一下bash脚本的测试。

一、shell脚本中的特殊变量

$0  获取当前执行的shell脚本的文件名

$n  获取当前执行的shell脚本的第n个参数值,n=1..9

$*  获取当前shell的所有参数 “$1 $2 $3 …

$#  获取当前shell命令行中参数的总个数

$$  获取当前shell的进程号(PID)

$!  执行上一个指令的PID

$?  获取执行的上一个指令的返回值(0 为成功, 非零为失败)

$@  这个程序的所有参数 “$1″ “$2″ “$3″ “…”

二、shell脚本中的测试

1、条件测试

   [expression] 命令行直接执行

   [[ expression ]] 关键字的变量引用 判断执行

  注:bash命令有执行状态返回值,而命令的执行结果与命令状态返回值截然不同的两个概念。其区别是命令执行后产生的结果,是否执行成功就有执行状态返回值判断 :echo$?返回值是0 执行成功,1-255 执行失败

2、整数测试

   expression :数值1 比较符号 数值2

   -gt :大于       $A -gt $B --> A>B

   -ge : 大于或等于 $A -ge $B --> A>=B

   -eq : 等于       $A -eq $B --> A=B

   -lt : 小于       $A -lt $B --> A<B

   -le : 小于或等于 $A -le $B --> A<=B

   -ne : 不等于     $A -ne $B --> A!=B

3、字符测试

  expression :字符1 比较符号 字符2

   > : 大于  < : 小于

   == : 等于

   =~ :判断左边的字符是否能够被右边的字符模式匹配

   注:字符匹配命令 [[ $opt1 =~ $opt2 ]],一般做行首行尾锚定,$opt2不要加引号。

   字符单目操作 :-z $STRING : 为空则为真,不空则为假

                  -n $STRING :为空则为假,不空则为真

4、组合测试

     &&:与  ||:或   !:非    

   短路操作

    与运算:1 && 1 =1 ,0 && {0,1} =0 ,1 && 0 =0  

    或运算:1 || {0 ,1} =1 , 0 ||  1 =1 , 0 ||  0 =0

5、文件测试

   操作符 文件路径

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

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

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

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

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

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

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

三、for循环结构

    语法结构:

       for 变量 in 列表 ;do

           语句1 ;语句2 ;···

       done

注:循环必须有退出条件,不然会成为死循环,此处列表即为限定条件。

四、while循环结构

    语法结构:

       while 测试条件 ;do

         语句1;语句2;···

       done

五、until循环结构

    语法结构:

       until 测试条件 ;do

          语句1;语句2;···

       done

六,for, while, until 三者的对比

三者如何退出循环:

for循环语句是遍历列表中的元素完成;                  

while循环语句是在循环体改变测试条件时,条件满足就循环,直到条件不再满足则退出循环;

until循环语句是在循环体改变测试条件时,条件不满足就循环,直到条件满足时则退出循环。

   实战演练

1、写一个脚本

   使用for循环统计/etc/fstab、/etc/rc.d/rc.sysinit、/etc/inittab文件中各自以#开头的行的行数和空白行数;

#!/bin/bash
for File in /etc/fstab /etc/rc.d/rc.sysinit /etc/inittab; do
  echo "$File:"
  echo -e "\t#lines: `grep "^#" $File | wc -l`"
  echo -e "\tspace lines: `grep "^$" $File | wc -l`"
done


2、写一个脚本

使用for循环,分别将user1、user2和user3加入到testgrp组中,以其为额外组;

#!/bin/bash
groupadd testgrp
for User in user1 user2 user3; do
  usermod -a -G testgrp $User
done


3、写一个脚本

  使用for循环,复制/etc/fstab、/etc/inittab和/etc/rc.d/init.d/functions文件至/tmp/目录中,并重命名为原有的名称之后加当前日期,如第一个文件为/tmp/fstab-2013-07-

#!/bin/bash
for File in /etc/fstab /etc/inittab /etc/rc.d/init.d/functions; do
   Filename= basename $File
  cp $File /tmp/$Filename-`date +%F`
done

 

4、写一个脚本

  求200以内所有为3的整数倍的整数之和;

#!/bin/bash
#
Sum=0
for I in {1..200}; do
  if [ $[$I%3] -eq 0 ]; then
    Sum=$[$Sum+$I]
  fi
done
echo "Sum: $Sum."


5、写一个脚本

  计算100以内所有奇数的和以及所有偶数的和;分别显示之

#

5、写一个脚本

  如果用户的ID号为偶数,则显示其名称和shell;对所有用户执行此操作;  

#!/bin/bash
while read LINE; do
  Uid=`echo $LINE | cut -d: -f3`
  if [ $[$Uid%2] -eq 0 ]; then
    echo $LINE | cut -d: -f1,7
  fi
done < /etc/passwd


6、写一个脚本

   每隔5秒查看hadoop用户是否登录,如果登录,显示其登录并退出;否则,显示当前时间,并说明hadoop尚未登录:

#!/bin/bash
who | grep "^hadoop" &> /dev/null
RetVal=$?
until [ $RetVal -eq 0 ]; do
  date
  sleep 5
  who | grep "^hadoop" &> /dev/null
  RetVal=$?
done
echo "hadoop is here."

7、写一个脚本

 使用for,while,until三个循环语句,计算100以内所有正整数的和;

fo语句

#!/bin/bash
#
  Sum=0
for I in {1..100}; do
  let Sum=$[$Sum+$I]
done
echo $Sum

while语句

#!/bin/bash
Sum=0
Count=1
while [ $Count -lt 100 ]; do
  let Sum+=$Count
  let Count++
done
echo $Sum

until语句

#!/bin/bash
Sum=0
Count=1
until [ $Count -gt 100 ]; do
  let Sum+=$Count
  let Count++
done
echo $Sum


8、写一个脚本

使用while和until分别实现“转换用户输入的字符为大写,除了quit(遇见quit退出);”

while语句

#!/bin/bash
read -p "A string: " String
while [ "$String" != 'quit' ]; do
  echo $String | tr 'a-z' 'A-Z'
  read -p "Next [quit for quiting]: " String
done

until语句

read -p "A string: " String
until [ "$String" == 'quit' ]; do
  echo $String | tr 'a-z' 'A-Z'
  read -p "Next [quit for quiting]: " String
done

9、写一个脚本

计算100以内所有偶数的和以及奇数的和;在一个循环中实现;

要求:分别使用for,while,until各自独立实现。

for语句

#!/bin/bash
EvenSum=0
OddSum=0
for I in {1..100}; do
  if [ $[$I%2] -eq 0 ]; then
    EvenSum=$[$EvenSum+$I]
  else
    OddSum=$[$OddSum+$I]
  fi
done
echo "EvenSum is: $EvenSum. OddSum is: $OddSum."

while语句

#!/bin/bash
EvenSum=0
OddSum=0
Count=0
while [ $Count -le 100 ]; do
  if [ $[$Count%2] -eq 0 ]; then
    let Sum+=$Count
    let count++
   echo "EvenSum is:$Sum"
  else
    let Sum+=$Count
   echo "OddSum is:$Sum"
  fi
done

until语句

#!/bin/bash
EvenSum=0
OddSum=0
Count=0
until [ $Count -gt 100 ]; do
  if [ $[$Count%2] -eq 0 ]; then
    let Sum+=$Count
    let count++
   echo "EvenSum is:$Sum"
  else
    let Sum+=$Count
   echo "OddSum is:$Sum"
  fi
done