Linux Bash编程超详细语法总结

系统 Linux
在Linux学习过程中,我们无可避免的会碰到一个既让人喜欢,又令人头疼的神奇的东西——bash编程,即shell脚本。本文带来的是bash编程的基础语法讲解。

[[316402]]

 在Linux学习过程中,我们无可避免的会碰到一个既让人喜欢,又令人头疼的神奇的东西——bash编程,即shell脚本。那么什么是shell脚本呢?shell是一个命令语言解释器,而shell脚本则是Linux命令的集合,按照预设的顺序依次解释执行,来完成特定的、较复杂的系统管理任务,类似于Windows中的批处理文件。本文带来的是bash编程的基础语法讲解。

bash编程之变量

bash变量类别

本地变量:只对当前shell进程有效的变量,对其它shell进程无效,包当前shell进程的子进程

  1. VAR_NAME=VALUE 

变量赋值:向变量的存储空间保存数据

变量引用:${VAR_NAME}  

  1. "":弱引用,里面的变量会被替换  
  2. '':强引用,里面的所有字符都是字面量,直接输出  

环境变量:对当前shell进程及其子shell有效,对其它的shell进程无效          

  1. 定义:export VAR_NAME=VALUE  
  2. 导出:export VAR_NAME  
  3. 撤消变量:unset VAR_NAME  
  4. 只读变量:readonly VAR_NAME 

局部变量: 对shell脚本中某代码片断有效,通常用于函数本地 

  1. local VAR_NAME=VALUE 

位置变量:用来接受变量指定位置的参数 

  1. $1,$2...,${10} 

特殊变量:shell对一些参数做特殊处理,这些参数只能被引用而不能被赋值 

  1. $#  传递到脚本的参数个数  
  2. $*  显示所有向脚本传递的参数                  #与位置变量不同,此选项参数可超过9个  
  3. $$  获取当前shell的进程号  
  4. $!  执行上一个指令的进程号  
  5. $?  获取执行的上一个指令的返回值              #0为执行成功,非零为执行失败  
  6. $-  显示shell使用的当前选项,与set命令功能相同  
  7. $@  与$*相同,但是使用时加引号,并在引号中返回每个参数 

查看变量: 

  1. set:查看当前shell进程中的所有变量  
  2. export, printenv, env:查看当前shell进程中的所有环境变量 

变量命名:

  •  1、不能使用程序中的关键字(保留字)
  •  2、只能使用数字、字母和下划线,且不能以数字开头
  •  3、要见名知义

变量类型: 

  1. 数值型:精确数值(整数),近似数值(浮点型)  
  2. 字符型:char,string  
  3. 布尔型:true, false 

类型转换: 

  1. 显式转换  
  2. 隐式转换 

bash的配置文件:

功能:设定本地变量,定义命令别名

  •  profile类:为交互式登录的用户提供配置 
  1. 全局:/etc/profile、/etc/profile.d/*.sh  
  2. 用户:~/.bash_profile 
  •  bashrc类:为非交互式的用户提供配置 
  1. 全局:/etc/bashrc  
  2. 用户:~/.bashrc 

bash编程之编写格式及执行方式

  •     编写格式:shell脚本第一行必须顶格写,用shebang定义指定的解释器来解释该脚本。 
  1. #!/bin/bash       #!即为shebang  
  2. # 其它的以#开头的行均为注释,会被解释器忽略,可用来注释脚本用途及版本,方便使用管理。 
  •  执行方式:bash编程属于面向过程编程,执行方式如下: 
  1. 顺序执行:按命令先后顺寻依次执行  
  2. 选择执行:测试条件,可能会多个测试条件,某条件满足时,则执行对应的分支  
  3. 循环执行:将同一段代码反复执行多次,因此,循环必须有退出条件;否则,则陷入死循环 
  •  bash执行选项: 
  1. bash -n SHELLNAME  #语法测试,测试是否存在语法错误  
  2. bash -x SHELLNAME  #模拟单步执行,显示每一步执行过程 

bash之算数运算与逻辑运算

  •  算数运算

定义整型变量:l

  1. et VAR_NAME=INTEGER_VALUE            #例如:let a=3  
  2. declare -i VAR_NAME=INTEGER_VALUE     #declare -i a=3 

实现算术运算的方式: 

  1. let VAR_NAME=ARITHMATIC_EXPRESSION  
  2. VAR_NAME=$[ARITHMATIC_EXRESSION]  
  3. VAR_NAME=$((EXPRESSION))  
  4. VAR_NAME=$(expr $num1 + $num2) 

算术运算符: 

  1. +:加法  
  2. -:减法  
  3. *:乘法  
  4. /:整除  
  5. %:取余数  
  6. **:乘幂 

注意:即使没有定义为整型变量,字符型的数字依然可以参与算术运算,bash会执行变量类型的隐式类型转换。

  •  逻辑运算 
  1. 布尔运算:真,假  
  2. 与运算:真 && 真 = 真  
  3.         真 && 假 = 假  
  4.         假 && 真 = 假  
  5.         假 && 假 = 假  
  6. 或运算:真 || 真 = 真  
  7.   真 || 假 = 真  
  8.   假 || 真 = 真  
  9.   假 || 假 = 假  
  10. 非运算:!真=假  
  11.         !假=真 

bash编程之条件测试语句

bash条件测试

整型测试:整数比较 

  1. 例如 [ $num1 -gt $num2 ]  
  2. -gt: 大于则为真  
  3. -lt: 小于则为真  
  4. -ge: 大于等于则为真  
  5. -le: 小于等于则为真 
  6.  -eq: 等于则为真  
  7. -ne: 不等于则为真 

字符测试:字符串比较 

  1. 双目:  
  2. 例如[[ "$str1" > "$str2" ]]  
  3. >: 大于则为真  
  4. <: 小于则为真  
  5. >=:大于等于则为真  
  6. <=:小于等于则为真  
  7. ==:等于则为真  
  8. !=:不等于则为真  
  9. 单目:  
  10. -n String: 是否不空,不空则为真,空则为假  
  11. -z String: 是否为空,空则为真,不空则假  
  12. 文件测试:判断文件的存在性及属性等  
  13. -a FILE:存在则为真;否则则为假;  
  14. -e FILE: 存在则为真;否则则为假;  
  15. -f FILE: 存在并且为普通文件,则为真;否则为假;  
  16. -d FILE: 存在并且为目录文件,则为真;否则为假; 
  17.  -L/-h FILE: 存在并且为符号链接文件,则为真;否则为假;  
  18. -b: 存在并且为块设备,则为真;否则为假;  
  19. -c: 存在并且为字符设备,则为真;否则为假  
  20. -S: 存在并且为套接字文件,则为真;否则为假  
  21. -p: 存在并且为命名管道,则为真;否则为假  
  22. -s FILE: 存在并且为非空文件则为值,否则为假;  
  23. -r FILE:文件可读为真,否则为假  
  24. -w FILE:文件可写为真,否则为假  
  25. -x FILE:文件可执行为真,否则为假  
  26. file1 -nt file2: file1的mtime新于file2则为真,否则为假;  
  27. file1 -ot file2:file1的mtime旧于file2则为真,否则为假;  
  28. 组合条件测试:在多个条件间实现逻辑运算  
  29. 与:[ condition1 -a condition2 ]  
  30.   condition1 && condition2  
  31. 或:[ condition1 -o condition2 ] 
  32.    condition1 || condition2  
  33. 非:[ -not condition ]  
  34.   ! condition  
  35. 与:COMMAND1 && COMMAND2  
  36. COMMAND1如果为假,则COMMAND2不执行  
  37. 或:COMMAND1 || COMMAND2  
  38. COMMAND1如果为真,则COMMAND2不执行  
  39. 非:! COMMAND 

条件测试之if语句 

  1. 1、if语句之单分支  
  2. 语句结构:  
  3. if 测试条件;then  
  4.    选择分支  
  5. fi  
  6. 表示条件测试状态返回值为值,则执行选择分支  
  7. 例:写一个脚本,接受一个参数,这个参数是用户名;如果此用户不存在,则创建该用户;  
  8. #!/bin/bash  
  9. if ! id $1 &> /dev/null;then  
  10.   useradd $1 
  11. fi  
  12. 2、if语句之双分支  
  13. 语句结构:  
  14. if 测试条件;then  
  15.    选择分支1  
  16. else  
  17.    选择分支2  
  18. fi  
  19. 两个分支仅执行其中之一  
  20. 例:通过命令行给定一个文件路径,而后判断:如果此文件中存在空白行,则显示其空白行的总数;否则,则显示无空白行;  
  21. #!/bin/bash  
  22. if grep "^[[:space]]*$" $1 &> /dev/null; then  
  23.   echo "$1 has $(grep "^[[:space]]*$" $1 | wc -l) blank lines."  
  24. else  
  25.   echo "No blank lines"  
  26. fi  
  27. 注意:如果把命令执行成功与否当作条件,则if语句后必须只跟命令本身,而不能引用。  
  28. 3、if语句之多分支  
  29. 语句结构:  
  30. if 条件1;then  
  31.      分支1  
  32. elif 条件2;then  
  33.      分支2  
  34. elif 条件3;then  
  35.      分支3  
  36.       ...  
  37. else  
  38.      分支n  
  39. fi  
  40. 例:传递一个用户名给脚本:如果此用户的id号为0,则显示说这是管理员;如果此用户的id号大于等于500,则显示说这是普通用户;否则,则说这是系统用户。  
  41. #!/bin/bash  
  42. if [ $# -lt 1 ]; then  
  43.   echo "Usage: `basename $0` username"  
  44.   exit 1  
  45. fi  
  46. if ! id -u $1 &> /dev/null; then  
  47.   echo "Usage: `basename $0` username"  
  48.   echo "No this user $1."  
  49.   exit 2  
  50. fi  
  51. if [ $(id -u $1) -eq 0 ]; then  
  52.   echo "Admin"  
  53. elif [ $(id -u $1) -ge 500 ]; then  
  54.   echo "Common user."  
  55. else  
  56.   echo "System user."  
  57. fi 

bash交互式编程 

  1. read [option] “prompt”-p:直接指定一个变量接受参数  
  2. -t timaout:指定等待接受参数的时间  
  3. -n:表示不换行  
  4. 例:输入用户名,可返回其shell  
  5. #!/bin/bash  
  6. read -p "Plz input a username: " userName  
  7. if id $userName &> /dev/null; then  
  8.     echo "The shell of $userName is `grep "^$userName\>" /etc/passwd | cut -d: -f7`."  
  9. else  
  10.     echo "No such user. stupid."  
  11. fi     

条件测试之case语句 

  1. case语句:有多个测试条件时,case语句会使得语法结构更明晰  
  2. 语句结构:  
  3. case 变量引用 in  
  4. PATTERN1)  
  5.   分支1  
  6. ;;  
  7. PATTERN2)  
  8.   分支2  
  9. ;;  
  10. ...  
  11. *)  
  12.   分支n  
  13. ;;  
  14. esac 

PATTERN:类同于文件名通配机制,但支持使用|表示或者 

  1.  a|b:  a或者b*:匹配任意长度的任意字符  
  2. ?: 匹配任意单个字符  
  3. []: 指定范围内的任意单个字符  
  4. 例:写一个脚本,完成如下任务,其使用形式如下所示:  
  5. script.sh {start|stop|restart|status}  
  6. 其中:如果参数为空,则显示帮助信息,并退出脚本;  
  7. 如果参数为start,则创建空文件/var/lock/subsys/script,并显示“starting script successfully.”  
  8. 如果参数为stop,则删除文件/var/lock/subsys/script,并显示“Stop script successfully.”  
  9. 如果参数为restart,则删除文件/var/locksubsys/script并重新创建,而后显示“Restarting script successfully.”  
  10. 如果参数为status,那么:如果文件/var/lock/subsys/script存在,则显示“Script is running…”,否则,则显示“Script is stopped.”  
  11. #!/bin/bash  
  12. file='/var/lock/subsys/script'  
  13. case $1 in  
  14. start)  
  15.   if [ -f $file ];then  
  16.   echo "Script is running..."  
  17.     exit 3  
  18.   else  
  19.   touch $file  
  20.   [ $? -eq 0 ] && echo "Starting script successfully."  
  21.   fi  
  22.   ;;  
  23. stop)  
  24.   if [ -f $file ];then  
  25.   rm -rf $file  
  26.   [ $? -eq 0 ] && echo "Stop script successfully."  
  27.   else  
  28.   echo "Script is stopped..."  
  29.   exit 4  
  30.   fi  
  31.   ;;  
  32. restart)  
  33.   if [ -f $file ];then  
  34.   rm -rf $file  
  35.   [ $? -eq 0 ] && echo "Stop script successfully"  
  36.   else   
  37.   echo "Script is stopped..."  
  38.   exit 5  
  39.   fi  
  40.   touch $file  
  41.   [ $? -eq 0 ] && echo "Starting script successfully"  
  42.   ;;  
  43. status)  
  44.   if [ -f $file ];then  
  45.   echo "Script is running..."  
  46.   else  
  47.   echo "Script is stopped."  
  48.   fi  
  49.   ;;  
  50. *)  
  51.   echo "`basename $0` {start|stop|restart|status}"  
  52.   exit 2  
  53.   ;;  
  54.  esac 

bash编程之循环语句

循环之for循环 

  1. 1、for语句格式一  
  2. 语句结构:  
  3. for 变量名 in 列表; do  
  4.     循环体  
  5. done  
  6. 列表:可包含一个或多个元素  
  7. 循环体:依赖于调用变量来实现其变化  
  8. 循环可嵌套  
  9. 退出条件:遍历元素列表结束  
  10. 例:求100以内所有正整数之和  
  11. #!/bin/bash  
  12. declare -i sum=0  
  13. for i in {1..100}; do  
  14.     let sum+=$i  
  15. done  
  16. echo $sum  
  17. 2、for语句格式二  
  18. for ((初始条件;测试条件;修改表达式)); do  
  19.       循环体  
  20. done  
  21. 先用初始条件和测试条件做判断,如果符合测试条件则执行循环体,再修改表达式,否则直接跳出循环。  
  22. 例:求100以内所有正整数之和(for二实现)  
  23. #!/bin/bash  
  24. declare -i sum=0  
  25. for ((counter=1;$counter <= 100; counter++)); do  
  26.   let sum+=$counter  
  27. done  
  28. echo $sum 

循环之while语句

while适用于循环次数未知,或不便用for直接生成较大的列表时 

  1. 语句结构:  
  2. while 测试条件; do  
  3.   循环体  
  4. done  
  5. 测试条件为真,进入循环;测试条件为假,退出循环  
  6. 例1:求100以内所有偶数之和,要求使用取模方法  
  7. #!/bin/bash  
  8. declare -i counter=1  
  9. declare -i sum=0  
  10. while [ $counter -le 100 ]; do  
  11.   if [ $[$counter%2] -eq 0 ]; then  
  12.      let sum+=$counter  
  13.   fi  
  14.   let counter++  
  15.  done  
  16. echo $sum  
  17. 例2:提示用户输入一个用户名,如果用户存在,就显示用户的ID号和shell;否则显示用户不存在;显示完成之后不退出,再次重复前面的操作,直到用户输入q或quit为止  
  18. #!/bin/bash  
  19. read -p "Plz enter a username: " userName  
  20. while [ "$userName" != 'q' -a "$userName" != 'quit' ]; do  
  21.   if id $userName &> /dev/null; then  
  22.      grep "^$userName\>" /etc/passwd | cut -d: -f3,7  
  23.   else  
  24.     echo "No such user."  
  25.   fi  
  26. read -p "Plz enter a username again: " userName  
  27. done  
  28. while特殊用法:遍历文本文件  
  29. 语句结构:  
  30. while read 变量名; do  
  31.   循环体  
  32. done < /path/to/somefile  
  33. 变量名,每循环一次,记忆了文件中一行文本  
  34. 例:显示ID号为偶数,且ID号同GID的用户的用户名、ID和SHELL  
  35. while read line; do  
  36.   userID=`echo $line | cut -d: -f3`  
  37.   groupID=`echo $line | cut -d: -f4`  
  38.   if [ $[$userID%2] -eq 0 -a $userID -eq $groupID ]; then  
  39.      echo $line | cut -d: -f1,3,7  
  40.   fi  
  41. done < /etc/passwd 

循环之until语句 

  1. 语句结构:  
  2. until 测试条件; do  
  3.       循环体  
  4. done  
  5. 测试条件为假,进入循环;测试条件为真,退出循环  
  6. 例:求100以内所有偶数之和,要求使用取模方法(until实现)  
  7. #!/bin/bash  
  8. declare -i counter=1  
  9. declare -i sum=0  
  10. until [ $counter -gt 100 ]; do  
  11.   if [ $[$counter%2] -eq 0 ]; then  
  12.      let sum+=$counter  
  13.   fi  
  14.   let counter++  
  15. done  
  16. echo $sum  
  17. 例:提示用户输入一个用户名,如果用户存在,就显示用户的ID号和shell;否则显示用户不存在;显示完成之后不退出,再次重复前面的操作,直到用户输入q或quit为止(until实现)  
  18. #!/bin/bash  
  19. read -p "Plz enter a username: " userName  
  20. until [ "$userName" = 'q' -a "$userName" = 'quit' ]; do  
  21.   if id $userName &> /dev/null; then  
  22.    grep "^$userName\>" /etc/passwd | cut -d: -f3,7  
  23. else  
  24. echo "No such user."  
  25. fi  
  26. read -p "Plz enter a username again: " userName  
  27. done 

循环之循环控制和shift 

  1. 循环控制命令:  
  2. break:提前退出循环  
  3. break [N]: 退出N层循环;N省略时表示退出break语句所在的循环  
  4. continue: 提前结束本轮循环,而直接进入下轮循环  
  5. continue [N]:提前第N层的循环的本轮循环,而直接进入下轮循环 

死循环: 

  1. #while体while true; do  
  2.       循环体  
  3. done  
  4. #until体  
  5. until false; do  
  6.       循环体  
  7. done  
  8. 例1:写一个脚本,判断给定的用户是否登录了当前系统  
  9. (1) 如果登录了,则脚本终止;  
  10. (2) 每5秒种,查看一次用户是否登录;  
  11. #!/bin/bash  
  12. while true; do  
  13.     who | grep "gentoo" &> /dev/null  
  14.     if [ $? -eq 0 ];then  
  15. break  
  16.     fi  
  17.     sleep 5  
  18. done  
  19. echo "gentoo is logged." 

shift: 

  1. 如果没有数字,只有shift 就是跳过一个参数获取下一个参数,如果加上数字,比如shift 2 ,跳过两个参数获取下一个参数。  
  2. 例:写一个脚本,使用形式如下所示      
  3. showifinfo.sh [-i INTERFACE|-a] [-v]  
  4. 要求:  
  5. 1、-i或-a不可同时使用,-i用于指定特定网卡接口,-a用于指定所有接口;  
  6. 显示接口的ip地址  
  7. 2、使用-v,则表示显示详细信息,显示接口的ip地址、子网掩码、广播地址;  
  8. 3、默认表示仅使用-a选项;  
  9. #!/bin/bash  
  10. allinterface=0  
  11. ifflag=0  
  12. verbose=0  
  13. interface=0  
  14. if [ $# -eq 0 ];then  
  15.   ifconfig | grep "inet addr:" | awk '{print $2}'  
  16. fi  
  17. while [ $# -ge 1 ];do  
  18.   case $1 in   
  19. -a)  
  20.  allinterface=1  
  21.  shift 1  
  22.   ;;  
  23. -i)  
  24.   ifflag=1  
  25.   interface=$2  
  26.   shift 2  
  27.   ;;  
  28. -v)  
  29.   verbose=1  
  30.   shift 1  
  31.   ;;  
  32.   *)  
  33. echo "error option"  
  34. exit 2  
  35.   ;;  
  36.   esac  
  37. done  
  38. if [ $allinterface -eq 1 ];then  
  39.   if [ $ifflag -eq 1 ];then  
  40.    echo "command not found"  
  41.     exit 5  
  42.   fi  
  43.   if [ $verbose -eq 1 ];then  
  44.     ifconfig | grep "inet addr:"  
  45.   else  
  46.     ifconfig | grep "inet addr:" | awk '{print $2}'  
  47.   fi  
  48. fi  
  49. if [ $ifflag -eq 1 ];then  
  50.   if [ $allinterface -eq 1 ];then  
  51.         echo "command not found"  
  52.         exit 5  
  53.   fi  
  54.  if [ $verbose -eq 1 ];then  
  55.     ifconfig $interface | grep "inet addr:"  
  56.   else  
  57.     ifconfig $interface | grep "inet addr:" | awk '{print $2}'  
  58.   fi  
  59. fi 

bash编程之函数

语法结构: 

  1. function F_NAME {      
  2.    函数体  
  3.   }  
  4.   F_NAME() {  
  5.     函数体  
  6.   } 

可调用:使用函数名,函数名出现的地方,会被自动替换为函数

函数的返回值:

函数的执行结果返回值:代码的输出

函数中使用打印语句:echo, printf

函数中调用的系统命令执行后返回的结果

执行状态返回值:

默认取决于函数体执行的最后一个命令状态结果

自定义退出状态码:return [0-255]

注意:函数体运行时,一旦遇到return语句,函数即返回;

函数可以接受参数:

在函数体中调用函数参数的方式同脚本中调用脚本参数的方式: 

  1. 位置参数  
  2. $1, $2, …  
  3. $#, $*, $@ 

例:写一个脚本,完成如下功能(使用函数):

1、提示用户输入一个可执行命令;

2、获取这个命令所依赖的所有库文件(使用ldd命令);

3、复制命令至/mnt/sysroot/对应的目录中

解释:假设,如果复制的是cat命令,其可执行程序的路径是/bin/cat,那么就要将/bin/cat复到/mnt/sysroot/bin/目录中,如果复制的是useradd命令,而useradd的可执行文件路径为/usr/sbin/useradd,那么就要将其复制到/mnt/sysroot/usr/sbin/目录中;

4、复制各库文件至/mnt/sysroot/对应的目录中; 

  1. #!/bin/bash  
  2. target=/mnt/sysroot/  
  3. [ -d $target ] || mkdir $target  
  4. preCommand() {  
  5.     if which $1 &> /dev/null; then  
  6.   commandPath=`which --skip-alias $1`  
  7.   return 0  
  8.     else  
  9.   echo "No such command."  
  10.   return 1  
  11.     fi  
  12.  
  13. commandCopy() {  
  14.     commandDir=`dirname $1`  
  15.     [ -d ${target}${commandDir} ] || mkdir -p ${target}${commandDir}  
  16.     [ -f ${target}${commandPath} ] || cp $1 ${target}${commandDir}  
  17.  
  18. libCopy() {  
  19.     for lib in `ldd $1 | egrep -o "/[^[:space:]]+"`; do  
  20. libDir=`dirname $lib`  
  21. [ -d ${target}${libDir} ] || mkdir -p ${target}${libDir}  
  22. [ -f ${target}${lib} ] || cp $lib ${target}${libDir}  
  23.     done  
  24. }  
  25.  read -p "Plz enter a command: " command  
  26. until [ "$command" == 'quit' ]; do  
  27.   if preCommand $command &> /dev/null; then  
  28.     commandCopy $commandPath  
  29.     libCopy $commandPath  
  30.   fi 
  31.   read -p "Plz enter a command: " command  
  32. done 

bash编程之信号捕捉

trap命令用于在shell程序中捕捉到信号,之后可以有三种反应方式:

  •  (1)执行一段程序来处理这一信号
  •  (2)接受信号的默认操作
  •  (3)忽视这一信号

trap对上面三种方式提供了三种基本形式:

第一种形式的trap命令在shell接收到signal list清单中数值相同的信号时,将执行双引号中的命令串。 

  1. trap 'commands' signal-list  
  2. trap "commands" signal-list 

第二种形式的trap命令恢复信号的默认操作: 

  1. trap signal-list 

第三种形式的trap命令允许忽视信号: 

  1. trap " " signal-list  
  2. trap 'COMMAND' SIGINT(表示关闭进程) 

例:写一个脚本,能够ping探测指定网络内的所有主机是否在线,当没有执行完时可接收ctrl+c命令退出。 

  1. #!/bin/bash  
  2. quitScript() {  
  3.    echo "Quit..."  
  4. }      
  5. trap 'quitScript; exit 5' SIGINT  
  6. cnetPing() {  
  7.   for i in {1..254}; do  
  8.     if ping -c 1 -W 1 $1.$i &> /dev/null; then  
  9.       echo "$1.$i is up."  
  10.      else  
  11.       echo "$1.$i is down."  
  12.     fi  
  13.     done  
  14.  
  15. bnetPing() {  
  16.   for j in {0..255}; do  
  17.     cnetPing $1.$j   
  18.   done  
  19.  
  20. anetPing() {  
  21. for m in {0..255}; do  
  22. bnetPing $1.$m  
  23. done  
  24.  
  25. netType=`echo $1 | cut -d"." -f1`  
  26. if [ $netType -ge 1 -a $netType -le 126 ]; then  
  27. anetPing $netType  
  28. elif [ $netType -ge 128 -a $netType -le 191 ]; then  
  29. bnetPing $(echo $1 | cut -d'.' -f1,2)  
  30. elif [ $netType -ge 192 -a $netType -le 223 ]; then  
  31. cnetPing $(echo $1 | cut -d'.' -f1-3)  
  32. else  
  33. echo "Wrong"  
  34. exit 2  
  35. fi 

bash编程之数组

数组:连续的多个独立内存空间,每个内存空间相当于一个变量

数组元素:数组名+索引(从0开始编号)

索引的表示方式:a[0], a[1]

声明数组: 

  1. declare -a ARRAR_NAME 

关联数组: 

  1. declare -A ARRAY_NAME 

支持稀疏格式:仅一维数组  

数组元素的赋值:

(1) 一次只赋值一个元素 

  1. a[0]=$RANDOM 

(2) 一次赋值全部元素 

  1. a=(red blue yellow green) 

(3) 指定索引进行赋值 

  1. a=([0]=green [3]=red [2]=blue [6]=yellow) 

(4) 用户输入 

  1. read -a ARRAY 

数组的访问:

用索引访问: 

  1. ARRAY[index] 

数组的长度: 

  1. ${#ARRAY[*]}  
  2. ${#ARRAY[@]} 

例:写一个脚本,生成10个随机数,保存至数组中;而后显示数组下标为偶数的元素 

  1. #!/bin/bash  
  2. for i in {0..9}; do  
  3.     rand[$i]=$RANDOM  
  4.     [ $[$i%2] -eq 0 ] && echo "$i:${rand[$i]}"  
  5. done 

从数组中挑选某元素: 

  1. ${ARRAY[@]:offset:number} 

切片: 

  1. offset: 偏移的元素个数  
  2. number: 取出的元素的个数  
  3. ${ARRAY[@]:offset}:取出偏移量后的所有元素  
  4. ${ARRAY[@]}: 取出所有元素 

数组复制:要使用${ARRAY[@]} 

  1. $@: 每个参数是一个独立的串  
  2. $*: 所有参数是一个串 

向数组中追加元素:非稀疏格式 

  1. week,   
  2. week[${#week[@]}] 

从数组中删除元素: 

  1. unset ARRAY[index] 

例:复制一个数组中下标为偶数的元素至一个新数组中 

  1. #!/bin/bash  
  2. declare -a mylogs  
  3. logs=(/var/log/*.log)  
  4. echo ${logs[@]} 
  5.  for i in `seq 0 ${#logs[@]}`; do  
  6.   if [ $[$i%2] -eq 0 ];then  
  7.     index=${#mylogs[@]}  
  8.      mylogs[$index]=${logs[$i]}  
  9.   fi  
  10. done  
  11. echo ${mylogs[@]} 

例2:生成10个随机数,升序排序 

  1. #!/bin/bash  
  2. for((i=0;i<10;i++))  
  3. do  
  4.   rnd[$i]=$RANDOM  
  5. done  
  6. echo -e "total=${#rnd[@]}\n${rnd[@]}\nBegin to sort"  
  7. for((i=9;i>=1;i--))  
  8. do  
  9.         for((j=0;j<i;j++))  
  10.   do 
  11.    if [ ${rnd[$j]} -gt ${rnd[$[$j+1]]} ] ;then  
  12.     swapValue=${rnd[$j]}  
  13.     rnd[$j]=${rnd[$[$j+1]]}  
  14.     rnd[$[$j+1]]=$swapValue  
  15.   fi  
  16.   done  
  17. done  
  18. echo ${rnd[@]} 

例3:打印九九乘法表 

  1. #!/bin/bashfor((i=1;i<=9;i++))  
  2. do   
  3. strLine=""  
  4.   for((j=1;i<=9;j++))  
  5.   do  
  6.     strLine=$strLine"$i*$j="$[$i*$j]"\t"  
  7.     [ $i -eq $j ] && echo -e $strLine && break  
  8.   done  
  9. done 

bash编程之字符串操作

字符串切片: 

  1. ${string:offset:length}  
  2. [root@scholar scripts]# string='hello word'  
  3. [root@scholar scripts]# echo ${string:2:4}  
  4. llo  
  5. 取尾部的指定个数的字符:  
  6. ${string: -length}  
  7. [root@scholar scripts]# echo ${string: -2}  
  8. rd 

取子串:基于模式

  •  ${variable#*word}:在variable中存储字串上,自左而右,查找第一次出现word,删除字符开始至此word处的所有内容;
  •  ${variable##*word}:在variable中存储字串上,自左而右,查找最后一次出现word,删除字符开始至此word处的所有内容; 
  1. file='/var/log/messages'  
  2. ${file#*/}: 返回的结果是var/log/messages  
  3. ${file##*/}: 返回messages 
  •  ${variable%word*}: 在variable中存储字串上,自右而左,查找第一次出现word,删除此word处至字串尾部的所有内容;
  •  ${variable%%world*}:在variable中存储字串上,自右而左,查找最后一次出现word,删除此word处至字串尾部的所有内容; 
  1. file='/var/log/messages'  
  2. ${file%*/}: 返回的结果是/var/log  
  3. ${file%%*/}: 返回结果为空  
  4. 例:url="http://www.redhat.com:80"  
  5. 取端口:${url##*:}  
  6. 取协议:${url%%:*} 

查找替换:

${variable/pattern/substi}: 替换第一次出现 

  1. #userinfo=`tail -1 /etc/passwd  
  2. #echo $userinfo  
  3. scholar:x:500:500:scholar:/home/scholar:/bin/bash  
  4. #echo ${userinfo/scholar/redhat}  
  5. redhat:x:500:500:scholar:/home/scholar:/bin/bash 

${variable//pattern/substi}:替换所有的出现 

  1. #echo ${userinfo//scholar/redhat}  
  2. redhat:x:500:500:redhat:/home/redhat:/bin/bash 

${variable/#pattern/substi}:替换行首被pattern匹配到的内容 

  1. #echo ${userinfo/#scholar/redhat}  
  2. redhat:x:500:500:scholar:/home/scholar:/bin/bash 

${variable/%pattern/substi}:替换行尾被pattern匹配到的内容 

  1. #echo ${userinfo/%bash/redhat}  
  2. scholar:x:500:500:scholar:/home/scholar:/bin/redhat 

pattern可以使用globbing中的元字符:* ?

查找删除:

${variable/pattern}:删除第一次出现 

  1. #echo ${userinfo/scholar}  
  2. :x:500:500:scholar:/home/scholar:/bin/bash 

${variable//pattern}:删除所有的出现 

  1. #echo ${userinfo//scholar}  
  2. :x:500:500::/home/:/bin/bash 

${variable/#pattern}:删除行首被pattern匹配到的内容 

  1. #echo ${userinfo/#scholar}  
  2. :x:500:500:scholar:/home/scholar:/bin/bash 

${variable/%pattern}:删除行尾被pattern匹配到的内容 

  1. #echo ${userinfo/%bash}  
  2. scholar:x:500:500:scholar:/home/scholar:/bin/ 

大小写转换:

小–>大:${variable^^} 

  1. #echo ${userinfo^^}  
  2. SCHOLAR:X:500:500:SCHOLAR:/HOME/SCHOLAR:/BIN/BASH 

大–>小:${variable,,} 

  1. #name="SCHOLAR"  
  2. #echo ${name,,}  
  3. scholar 

变量赋值操作:

${variable:-string}:variable为空或未设定,那么返回string,否则,返回variable变量的值;

${variable:=string}:variable为空或未设定,则返回string,且将string赋值给变量variable,否则,返回variable的值;

为脚本使用配置文件,并确保某变量有可用值的方式

variable=${variable:-default vaule}

写个脚本,配置etc目录;

(1) 在配置文件中定义变量;

(2) 在脚本中source配置文件; 

  1. #!/bin/bash  
  2. [ -f /etc/sysconfig/network ] && source /etc/network/network  
  3. [-z "$HOSTAME" -o "$HOSTNAME" = '(none)' ] || HOSTNAME ='localhost'  
  4. /bin/hostname $HOSTNAME  
  5. /bin/hostname 

mktemp命令:

mktemp [OPTIONS] filename.XXX 

  1. -d: 创建临时目录  
  2. --tmpdir=/path/to/somewhere :指定临时文件所在的目录  
  3. mktemp /tmp/tmp.XXX                    #XXX生成相同数量随机字符  
  4. mktemp --tmpdir=/var/tmp tmp.XXX       #指定目录创建临时文件  
  5. mktemp --tmpdir=/var/tmp -d tmp.XXX    #指定目录创建临时目录 

install命令:

install [OPTIONS] SOURCE DEST

install [OPTIONS] SOURCE… DIR

install [OPTIONS] -d DIR … 

  1. 增强型的复制命令:  
  2. -o OWNER  
  3. -g GROUP  
  4. -m MODE  
  5. -d : 创建目录  
  6. install /etc/fstab /tmp                 #复制文件到指定目录  
  7. install --mode=644 /etc/fstab /tmp/     #复制时指定权限  
  8. install --owner=scholar /etc/fstab /tmp #复制时指定属主  
  9. install --group=scholar /etc/fstab /tmp #复制时指定属组  
  10. install -d /tmp/install                 #创建目录  

 

责任编辑:庞桂玉 来源: Linux学习
相关推荐

2010-06-23 16:05:36

Linux Bash

2010-06-23 15:36:23

Linux Bug B

2022-08-01 10:11:24

Bash编程易错代码

2019-11-08 15:10:59

BashBash编程Linux

2010-06-23 14:45:02

Linux Bash

2021-06-01 08:00:43

KubernetesCentOS版集群

2020-06-19 09:55:00

Redis数据库字符串

2010-06-23 15:55:36

Linux Bash

2009-12-25 09:47:05

LinuxShell编程bash

2017-10-30 16:50:41

Linuxconst

2011-06-07 11:14:51

JAVAJSP

2019-08-05 09:19:45

PG事务隔离级别数据库

2022-07-29 11:39:31

​WindowLinux双系统

2009-12-25 09:55:18

LinuxShell编程Shell基本语法

2023-08-23 12:12:45

BashLinux

2021-03-17 13:33:02

BashUnixLinux

2020-04-30 09:30:32

Linux 监视器 GitHub

2019-08-02 09:13:22

Linux脚本语言欢聚时代

2020-07-22 16:40:23

增删改查Java代码

2019-10-22 07:50:45

SqlServer数据库触发器
点赞
收藏

51CTO技术栈公众号