SHELL编程语法

变量

    bash shell 使用一种称为环境变量的特性来存储关于shell会话和工作环境的信息环境变量的名字由此而来。该特性还允许你将数据存储在内存中以便于在shell中运行的程序或脚本访问它们。这是一种便捷的、用于存储持久性数据的方式这些数据可以标识用户账户、系统、shell或任何需要存储的内容的特性。

bash shell中共有两种类型的环境变量

本地变量: 只在创建它们的shell中可见

   # test=”testing”  #设置本地环境变量

   # echo $test

全局变量: 在shell会话和该shell中产生的任何子进程中都可见。

    # printenv # 查看所有已设置的全局环境变量

    # echo $VAR_NAME 查看某个环境变量的值

    全局环境变量的设置

        # test=”this is a test variable” # 先创建一个本地环境变量

        # export test # 然后将它导出到全局环境变量

移除环境变量

    # unset VAR_NAME

    # unset test

    在子进程中移除全局环境变量时只对子进程有效在父进程中全局环境变量仍然存在


特殊变量

$$: Shell本身的PIDProcessID      
$!: Shell最后运行的后台Process的PID      
$?: 最后运行的命令的结束代码返回值      
$-: 使用Set命令设定的Flag一览      
$*: 所有参数列表。如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。      
$@: 所有参数列表。如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。      
$#: 添加到Shell的参数个数      
$0: Shell本身的文件名      
$1$n: 添加到Shell的各参数值。$1是第1参数、$2是第2参数…


bash编程条件判断

脚本开头第一行#! shabang指定脚本使用的解释器

#!/bin/bash

#!/bin/sh

#/usr/bin/python

#!/bin/sed

#!/bin/awk

其他行#号开头或者#号之后的内容表示注释在””,’’和转义符\结合使用的#号表示”#”字符本身

if语句的使用格式

    if CMD
    then
        CMD 
    fi
或者
    if CMD; then
        CMD
    fi
#!/bin/bash
if [ $UID -eq 0 ]; then
    cat /etc/shadow
fi

上面的例子如果是root用户则查看/etc/shadow 文件内容。

if还可以这样用

    if CMD; then
        CMD1
    else
        CMD2
    fi

表示如果if后跟的条件为真则执行CMD1否则执行CMD2

#!/bin/bash
if [ $UID -eq 0 ]; then
    cat /etc/shadow
else
    echo "need root." 
    exit 1
fi


如果为root用户则查看/etc/shadow否则提示退出

if语句还可以嵌套

    if TEST1; then
        if TEST2; then
            CMD1
        fi
    else
        CMD2
    fi

也可以使用多分支if语句

    if TEST1;then
        CMD
    elif TEST2; then
        CMD2
    elif TEST3; then
        CMD3
    …
    elif TESTn; then
        CMDn
    fi

写一个脚本判断输入的参数是文件还是目录给出相应的提示

#!/bin/bash

if [ $# -ne 1 ]; then
    echo "Usage: `basename $0` [FILE|DIRECTORY]"
    exit 5
fi

if [ -f $1 ];then
    echo "$1 is a file"
elif [ -d $1 ]; then
    echo "$1 is a directory."
else
    echo "Usage: `basename $0` [FILE|DIRECTORY]"
    exit 5
fi


 bash编程循环语句


for循环语句

for var in list
do
    commands
done

list中放着变量值的列表变量var遍历列表中的每一个值去一次值执行一次循环直到遍历结束为止。通常用于循环次数已知的情况。

for还有另外一种使用格式

for ((初始条件;测试条件;修改表达式)); do

    循环体

done

求100以内的正整数之和

#!/bin/bash

declare -i sum=0
 i  {1..100}

    let sum+=$i
done
echo "$sum"

#!/bin/bash

declare -i sum=0

 ((i=1;i <= 100; i++));
    let sum+=$i
done

echo "$sum"

两种格式的for循环都可以


while循环

使用格式

while TESTdo
    commands
done

当测试条件为真进入循环条件为假则退出循环


until循环

使用格式

until TEST; do
    commands
done

当条件为假时进入循环为真时退出循环


用while循环和until循环求100内的正整数之和

#!/bin/bash

declare -i sum=0
declare -i var=1
 [ $var -le 100 ];
    let sum+=$var
    let var++
done
echo "$sum"

#!/bin/bash

declare -i var=1
declare -i sum=0

until [ $var -gt 100 ];do
    let sum+=$var
    let var++
done
echo "$sum"


case语句

有多个测试条件时用case语句比if语句结构更清晰

case $VAR in
PATTERN1)
    commands
    ;;
PATTERN2)
    commands
    ;;
…
PATTERNn)
    commands
    ;;
*)
    commands
    ;;
esac

上面是case语句的使用格式PATTERN使用文件名通配只是使用|表示或者。a|b

 

bash函数

定义函数

function name {
    commands
}
        name() {
    commands
}

函数调用函数名出现的地方会被自动替换为函数。

返回值

函数的执行结果返回值代码的输出
    函数中的打印语句echo, print
    函数中调用的系统命令执行后返回的结果
执行状态返回值
    函数体中最后一次执行的命令状态结果
    自定函数执行状态的返回值return #

函数应用举例:服务脚本

  #!/bin/bash
  #
  # chkconfig: 2345 67 34
  #
  srvName=$(basename $0)
  lockFile=/var/lock/subsys/$srvName
  start() {
      if [ -f $lockFile ];then
   echo "$srvName is already running."
   return 1
      else
   touch $lockFile
   [ $? -eq 0 ] && echo "Starting $srvName OK."
   return 0
       fi
  }
  stop() {
      if [ -f $lockFile ];then
   rm -f $lockFile &> /dev/null
   [ $? -eq 0 ] && echo "Stop $srvName OK" && return 0 
      else
   echo "$srvName is not started."
   return 1
      fi
  } 
  status() {
      if [ -f $lockFile ]; then
   echo "$srvName is running."
      else
   echo "$srvName is stopped."
      fi
      return 0
  }
  usage() {
       echo "Usage: $srvName {start|stop|restart|status}"
       return 0
  }
  case $1 in
  start)
   start
   ;;
  stop)
   stop ;;
  restart)
   stop
   start ;;
  status)
   status ;;
  *)
   usage
   exit 1 ;;
  esac


循环控制

break命令: 命令式在处理过程中跳出循环的一种简单方.可以使用break命令退出任何类型的循环,包括while循环和until循环.

1、跳出单循环

    shell执行break命令式它试图跳出当前正在处理的循环

#!/bin/bash

 i  {1..5};
     [ $i -eq 3 ];then
        break
    fi
    echo "$i"
done
echo "the loop is completed"

[root@bogon ~]# ./3test.sh       
1      
2      
the loop is completed

当i去3时执行break跳出了for循环。

2、跳出内循环

    使用多循环时 break命令自动终止所在的最里面的内部循环

3、跳出外循环

    可能有时处于内循环但需要停止外循环。break命令包括单独的命令行参数值  break n

    n表明要跳出的循环级别。默认情况下n是1代表跳出当前循环。如果将n设置为2break命令将停止外循环的下一级循环

#!/bin/bash

 i  {1,2,3};
    echo "outer loop $i"
     ((j=1; j < 100; j++));
         [ $j -gt 4 ]; then
             break 2
        fi
        echo "inner loop $j"
    done
done

[root@bogon ~]# ./4test.sh       
outer loop 1      
inner loop 1      
inner loop 2      
inner loop 3      
inner loop 4

continue命令是一种提前停止循环内命令,而不完全终止循环的方法。这就允许在循环中设置shell不执行命令的条件。

#!/bin/bash
 
for ((i=1;i < 15; i++));do
    if [ $i -gt 5 ] && [ $i -lt 10 ]; then
        continue
    fi
    echo "$i"
done 

[root@bogon ~]# ./5test.sh 
1
2
3
4
5
10
11
12
13
14


信号捕获:

Linux使用信号与系统上运行的进程进行通信。常用的信号

1 SIGHUP 挂起进程

2 SIGINT 中断进程

3 SIGQUIT 停止进程

9SIGKILL 无条件终止进程

15 SIGTERM 如果可能的话终止进程

17 SIGSTOP 无条件停止但不终止它

18 SIGTSTP 停止或暂停进程但不终止它

19 SIGCONT 重新启动停止的进程

默认情况下bash shell会忽略它接受的任何SIGQUIT3和SIGTERM5信号以防止交互的shell意外终止

捕获信号

    trap: 可以在信号出现时捕获信号和执行其他命令

    trap CMDs SIGNALs

#!/bin/bash

trap "echo testing" SIGINT SIGTERM

echo "This is a test script."
declare -i $var=1
 [ $var -le 10 ];
    echo "Loop $var"
    sleep 5
    let var++
done
echo �Ce "\033[31mEND\033[0m"


捕获脚本退出

    除了在shell脚本中捕获信号之外还可以在shell脚本退出时捕获它们。这是一种在shell完成作业时执行命令的便捷方式。

#!/bin/bash

trap "echo BYE" EXIT

declare -i var=1
 [ $var -le 5 ]

    echo "Loop #$var"
    sleep 2
    let var++
done
 
[root@bogon ~]# ./2test.sh 
Loop #1
Loop #2
Loop #3
Loop #4
Loop #5
BYE

 

移除捕获

要移除捕获使用破折号作为命令和想要恢复正常行为的信号列表

    trap �C SIGNAL

#!/bin/bash

trap "echo BYE" EXIT

declare -i var=1
while [ $var -le 5 ]
do
    echo "Loop #$var"
    sleep 2
    let var++
done
trap - EXIT
echo "removed the trip"
 
 


[root@bogon ~]# ./2test.sh 
Loop #1
Loop #2
Loop #3
Loop #4
Loop #5
removed the trip

如果在移除捕获之前接收到信号,仍然将会根据trap命令处理该信号

[root@bogon ~]# ./2test.sh 
Loop #1
^CBYE


数组

环境变量的一个非常好的特性就是能够当作数组使用。数组是能保存多个值的变量。数组中的值既可以分别引用也可以作为整体引用。

数组名和索引来表示数组中的变量

索引的表达方式

    数字索引 array[index]

       a[0], a[1]... a[n]

    bash 4.0之后开始支持关联数组可以指定一个字串当索引

        a[car], a[apple]

   declare -a 定义数组

    declare -A 定义关联数组

数组赋值

要为某个环境变量设置多个值只需将它们列出在圆括号中各值以空格分隔

# test=(1 two 3 4)

一次对一个数组元素赋值

# a[0]=$RANDOM

按索引赋值

# a=([0]=green [3]=orange [2]=yellow)

数组的访问

用索引访问数组中的元素 ARRAY[index]

整个数组 ${$array[@]}或者${$array[*]}

数组的长度

${#array[*]}或者${#array[@]}


从数组中挑选某元素
    ${ARRY[@]:offset:number}
        切片机制
        offset: 是指偏移量
       number取出元素的个数
        ${array[@]:3:4} 取出从第4个元素开始的4个元素array[3] array[4] array[5] array[6]

    ${ARRAY[@]:offset}取出偏移量后的所有元素
    ${ARRAY[@]}: 取出所有元素

打印九九乘法表

#!/bin/bash
for i in {1..9};do
    for ((j=1;j<=$i;j++));do
        let val=$i*$j
        valu[$j]="${i}x${j}=$val"
    done
    echo ${valu[@]}
done
     
[root@bogon scripts]# ./chengfabiao.sh 
1x1=1
2x1=2 2x2=4
3x1=3 3x2=6 3x3=9
4x1=4 4x2=8 4x3=12 4x4=16
5x1=5 5x2=10 5x3=15 5x4=20 5x5=25
6x1=6 6x2=12 6x3=18 6x4=24 6x5=30 6x6=36
7x1=7 7x2=14 7x3=21 7x4=28 7x5=35 7x6=42 7x7=49
8x1=8 8x2=16 8x3=24 8x4=32 8x5=40 8x6=48 8x7=56 8x8=64
9x1=9 9x2=18 9x3=27 9x4=36 9x5=45 9x6=54 9x7=63 9x8=72 9x9=81



你可能感兴趣的:(shell,脚本,bash)