Shell脚本

一、变量

1.1 变量赋值

  • 直接赋值
#!/bin/bash
name="tanqing"
declare -i num=123  #声明整数型变量
declare -a lists=("a" "b" "c")  #定义数组
  • 间接赋值
#!/bin/bash
read -p "please insert a num: " num 
echo $num

1.2 命令替换

将命令执行的结果保存给变量,需要做命令替换,有如下两种方式

#!/bin/bash
#Step1
num1=10
num2=20
sum=`expr $num1 + $num2`

#Step2
num1=10
num2=20
sum=$(expr $num1 + $num2)

1.3 内置变量

内置变量 作用
$0 脚本名
$1-$10 位置参数1-10
$# 传递位置参数的总个数
$@ 所有位置参数(每个作为单独字符串)
$* 所有位置参数(作为单个字符串)
$? 返回值
$$ 脚本进程的PID

二、数值运算

  • 方法1
#!/bin/bash
num1=10
num2=20
sum=$(($um1+$num2))
echo $sum
  • 方法2
#!/bin/bash
num1=10
num2=20
sum=$(expr $num1 + $num2) #注意运算符两边必须有空格
echo $sum
  • 方法3
#!/bin/bash
num1=10
num2=20
let sum=$num1+$num2 #注意运算符两边不能有空格
echo $sum

三、条件测试

  • 测试方法
# [ -f /var/log/message ]   #中括号测试
# test -f /var/log/message  # test关键字测试
  • 测试变量
选项 说明
-f 测试指定文件是否存在
-d 测试指定目录是否存在
-e 测试指定目录/文件是否存在
-z 测试字符串长度是否为0
$ 测试字符串长度是否为0
-n 测试字符串长度是否不为0
-S 测试指定文件是否是Socket文件
-w 测试文件是否有写权限
-r 测试文件是否有读权限
-x 测试文件是否有执行权限
-L 测试文件是否是一个链接文件

四、运算符

  • 算数运算符
运算符 说明
+ 加法
- 乘法
* 乘法
/ 除法
% 取模
  • 关系运算符
运算符 说明
=,==,-eq 是否相等
-ne,!= 是否不相等
-ge 是否大于等于
-gt 是否大于
-le 是否小于等于
-lt 是否小于
  • 逻辑运算符
运算符 说明
-a and,表示前面和后面的表达式都为真才为真
-o or,表时前面或后面的表达式有一个为真既为真
&& 逻辑与,前面命令执行成功,执行后面的命令
|| 逻辑非,前面命令执行失败,执行后面的命令
; 前面命令执行完毕,执行后面的命令

五、流程控制

5.1 if判断

  • if 单分支
#!/bin/bash
num1=10
num2=20
if [ $num2 -ge $num1 ];then
  echo "$num2大于${num1}."
else
  echo "$num2小于${$num1}"
fi
  • if 多分支
#!/bin/bash
num1=10
if [ $num1 -gt 100 ];then
  echo "$num1大于100"
elif [ $num1 -gt 50 ];then
  echo "$num1大于50"
elif [ $num1 -gt 10 ];then
  echo "$num1大于10"
else
  echo "$num1小于10"
fi

5.2 case判断

#!/bin/bash
#
case 变量 in
start)
    命令;;
stop)
    命令;;
restart)
    命令;;
status
    命令;;
*)
    命令;;
esac

case 支持 glob 风格的通配符:

*:任意长度的任意字符;
?:任意单个字符;
[ ]:范围内任意单个字符;
a|b:a 或 b;

5.3 for循环

#!/bin/bash
#step1
for i in `seq 1 10`;do
  echo "$i"
done

#step2
for i in {1..10};do
  echo "$i"
done

#step3
for i in 1 2 3 4 5 6 7 8 9 10;do
  echo "$i"
done

5.4 while循环

#!/bin/bash
#step1 死循环
while true;do
  echo "死循环."
done

#step2 跳出循环
i=0
while [ $i -lt 10 ];do
  let i++
  if [ $i -eq 5 ];then
    continue
  fi
  echo "$i"
done

#step 中止循环
i=0
while [ $i -lt 10 ];do
  let i++
  if [ $i -eq 5 ];then
    break
  fi
  echo "$i"
done

六、数组

  • 普通数组定义:declare -a myarray
  • 关联数组定义:declare -A myarray
  • 数组引用:${myarray[index]}

6.1 数组赋值

# ARRAY_NAME[INDEX]=value  #一次只赋值一个元素
# ARRAY_NAME=("VAL1"  "VAL2"  "VAL3"  ...)  #一次赋值多个元素
# ARRAY_NAME=([0]="VAL1"  [3]="VAL4" ...)  #赋值不连续的索引,稀疏格式

注意:bash-4及之后的版本,支持自定义索引格式,而不仅仅是0,1,2,...数字格式;此类数组称之为“关联数组”

图片

6.2 数组的操作

  • 取数组长度:${#ARRAY_NAME[*]},${#ARRAY_NAME[@]}
  • 引用数组中的所有元素:${ARRAY_NAME[*]},${ARRAY_NAME[@]}
  • 数组切片:${ARRAY_NAME[@]:offset:number}

offset:要跳过的元素个数,起始元素位置;
number:要取出的元素个数;省略number时,表示取偏移量之后的所有元素;

图片

  • 追加元素:ARRAY_NAME[${#ARRAY_NAME[*]}]=VALUE 元素的索引为元素的长度
  • 删除元素:unset  ARRAY[INDEX]

七、信号捕捉

进程在运行的时候,我们可以对进程发送信号来控制进程,信号有很多种,如中止、结束、挂起、重载等,在脚本运行过程中,也有可能因为误操作或者其他异常情况导致脚本中断运行,我们可能在进程中止前做一些特定操作,就需要用到信号捕捉。

  • 查看所有信号:kill -l ; trap -l
  • 捕捉信号:trap "捕捉到信号后执行的命令" 信号

下列代码正常执行完会删除临时文件,但如果被用户按CTRL+C中止,则不会执行rmtmp函数,而当信号捕捉到SIGINT信号(CTRL+C)时,执行rmtmp函数。

#!/bin/bash
declare -a tmpfiles
function rmtmp(){
        rm -f ${tmpfiles[@]}
        echo "删除临时文件完毕"
}
trap 'rmtmp' SIGINT
for i in {1..10};do
        sleep 1;
        tmp_file=`mktemp /tmp/test.XXXX`;
        echo "$i" | tee $tmp_file;
        tmpfiles[${#tmpfiles[*]}]=$tmp_file
done
rmtmp

八、字符串处理

  • 字符串切片:${var:offset:number},和数组切片一致

图片

8.1 查找替换

  • 替换一次:${var/oldstr/newstr}查找var所表示的字符串中,将第一次匹配到的字符串替换。
[root@dayet ~]# str="This is test str. test test test ~"
[root@dayet ~]# echo "${str/test/TEST}"
This is TEST str. test test test ~
  • 全局替换:${var//oldstr/newstr}查找var所表示的字符串中,将所有匹配到的字符串替换。
[root@dayet ~]# str="This is test str. test test test ~"
[root@dayet ~]# echo "${str//test/TEST}"
This is TEST str. TEST TEST TEST ~
  • 行首匹配替换:${var/#oldstr/newstr}:查找var所表示的字符串中,将行首被oldstr所匹配到的字符串替换。
[root@dayet ~]# str="root:x:0:0:root:/root:/bin/bash"
[root@dayet ~]# echo ${str/#root/ROOT}
ROOT:x:0:0:root:/root:/bin/bash
  • 行首匹配替换:${var/%oldstr/newstr}:查找var所表示的字符串中,将行尾被oldstr所匹配到的字符串替换。
[root@dayet ~]# str='This is test . test test test'
[root@dayet ~]# echo ${str/%test/TEST}
This is test . test test TEST
  • 查找删除:newstr处为空即可。

8.2 模式匹配提取字符串

  • ${var#*word}:其中word是指定的分隔符;从左向右查找var变量所存储的字符串中,第一次出现的word分隔符,删除字符串开头到分隔符之间的所有字符;

图片

  • ${var##*word}:其中word是指定的分隔符;从左向右查找var变量所存储的字符串中,最后一次出现的word分隔符,删除字符串开头到分隔符之间的所有字符;

图片

  • ${var%word*}:其中word是指定的分隔符;从右向左查找var变量所存储的字符串中,第一次出现的word分隔符,删除此分隔符到字符串尾部之间的所有字符;

图片

  • ${var%%word*}:其中word是指定的分隔符;从右向左查找var变量所存储的字符串中,最后一次出现的word分隔符,删除此分隔符到字符串尾部之间的所有字符;

图片

8.3 大小写转换

  • ${var^^}:把var中的所有小写字符转换为大写;

图片

  • ${var,,}:把var中的所有大写字符转换为小写;

图片

九、函数

  • 函数定义
#!/bin/bash
function test(){
  echo "This is test function"
}
test
  • 函数调用:直接输入函数名就行,不用加()
  • 函数传参:函数内接收参数的变量是$1,$2,$3...,和脚本运行的的位置变量同名,因此在函数内如果要接收shell位置参数需要将位置变量保存到全局变量中。
#!/bin/bash
name=$1
function say_hello(){
    echo "hello,$1"
}
say_hello $name
  • 函数返回值:用return关键字

十、重定向

命令的输出分为标准输出(1)和错误输出(2),默认只重定向标准输出。

示例 说明
> 覆盖重定向,会将源文件内容清空
>> 追加重定向
command 1> a.txt 标准输出重定向
command > a.txt 标准输出重定向
command 2> a.txt 错误输出重定向
command > a.txt 2>&1 标准输出和错误输出都重定向,2&1表示错误输出等于于标准输出
command 1>a.txt 2>a.txt 标准输出和错误输出都重定向
>/dev/null 将标准输出屏蔽
>/dev/null 将错误输出屏蔽
&> a.txt 正确输出和错误输出都重定向
posted @ 2021-09-30 11:12  相信童话  阅读(118)  评论(0)    收藏  举报