Shell脚本基础

  1. Shell脚本基础
    1. 变量
    2. 数组
    3. 运算符
      1. 算术运算符
      2. 关系运算符
      3. 布尔运算符
      4. 逻辑运算符
      5. 字符串运算符
      6. 文件测试运算符
    4. 流程控制
    5. 函数

Shell脚本基础

Kernel

Linux内核主要是为了和硬件交互

Shell

  • 命令解释器

  • Shell是一个用C语言编写的程序,它是用户使用Linux的桥梁,Shell既是一种命令语言,也是一种程序设计语言

  • Shell是指一种应用程序,这个应用提供了一个界面,用户通过这个界面访问操作系统内核的服务

声明

  • #!声明,告诉系统其后路径所指定的程序即是解释此脚本文件的Shell程序
#!/bin/bash
echo "Hello world!"

运行sh脚本的几种方式

./hello.sh
/root/hello.sh #绝对路径,必须是可执行文件
sh hello.sh #普通文件,脚本文件都可以
source hello.sh #与前面的不同,不会重新打开一个进程运行脚本,基于当前bash运行脚本

export

变量的引用顺序为:从当前进程查询变量,如果当前进程没有这个变量,则从父进程查询这个变量

如果使用export修饰变量,那么这个变量对于子进程就是可见的

变量

变量定义规则

定义变量时,变量名不加$

  • 命名只能使用英文字母,数字和下划线,首字符不能以数字开头
  • 中间不能有空格
  • 不能使用bash关键字(help可以查看保留关键字)

注意等号两侧避免使用空格

变量类型

  • 局部变量
    • 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其它shell启动的程序不能访问局部变量
  • 环境变量
    • 所有程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行
  • Shell变量
    • shell变量是由shell程序设置的特殊变量,shell变量中有一部分是环境变量,有一部分是局部变量
#变量的声明
name1="bob"
name2='zhang san'
#赋值
name3=$name1
echo $name3 #bob

字符串变量

  • 单引号
    • 单引号里的任何字符都会照样输出,单引号中字符串中的变量是无效的
    • 单引号字符串中不能出现单独一个的单引号,但可以成对出现,作为字符串拼接使用
  • 双引号
    • 双引号里可以有变量
    • 双引号里可以出现转义字符
b=6
name=bob
echo 'a$b' #a$b
echo "a$b" #a6

#字符串拼接
echo 'My name is' $name '.' # My name is bob .

#定义字符串
str='abcdefg'

#截取字符串,代表从索引1开始截取3位
echo ${str:1:3} #bcd

数组

bash支持一维数组(不支持多维数组),并没有限定数组的大小

数组下标由0开始编号,获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于0

#定义一个数组,不同元素用空格分隔
fav=("唱" "跳" "RAP" "篮球")

#取数组中的值,下标取值,从0开始
echo ${fav[0]} #唱

#获取数组所有元素
echo ${fav[@]} #唱 跳 RAP 篮球

#也可以使用数字下标来定义数组
fav[4]="游泳"
echo ${fav[4]}

运算符

算术运算符

直接使用运算符是无效的,如echo $a+$b只会显示1+2这样的结果

原生bash不支持简单的数学运算,但是可以通过其他命令来实现,这里使用expr来运算

a=1
b=2
echo $a+$b #1+2
echo `expr $a+$b` #3
运算符 说明 举例
+ 加法 expr $a + $b 结果为 30。
- 减法 expr $a - $b 结果为 -10。
\* 乘法 expr $a \* $b 结果为 200。
/ 除法 expr $b / $a 结果为 2。
% 取余 expr $b % $a 结果为 0。
= 赋值 a=$b 把变量 b 的值赋给 a。
== 相等。用于比较两个数字,相同则返回 true。 [ $a == $b ] 返回 false。
!= 不相等。用于比较两个数字,不相同则返回 true。 [ $a != $b ] 返回 true。

[ ]命令是Shell脚本中进行条件判断的基础工具之一

注意:条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 **[ $a == $b ]**。

乘号(*)前边必须加反斜杠()才能实现乘法运算;

如果使用 $(())则可以直接用运算符,效果和expr相同

使用a=${b}的效果和a=$b也是等价的

例如

a=10
b=20
echo $((a*b))
a=10
b=20

if [ $a == $b ]
then
   echo "a等于b"
fi

if [ $a != $b ]
then
  echo "a不等于b"
fi

关系运算符

关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

下表列出了常用的关系运算符,假定变量 a 为 10,变量 b 为 20:

运算符 说明 举例
-eq 检测两个数是否相等,相等返回 true。 [ $a -eq $b ] 返回 false。
-ne 检测两个数是否不相等,不相等返回 true。 [ $a -ne $b ] 返回 true。
-gt 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ] 返回 false。
-lt 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ] 返回 true。
-ge 检测左边的数是否大于等于右边的,如果是,则返回 true。 [ $a -ge $b ] 返回 false。
-le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ] 返回 true。
a=10
b=20

if [ $a -eq $b ]
then
  echo "a等于b"
else
  echo "a不等于b"
fi

if [ $a -lt $b ]
then
  echo "a小于b"
fi

如果使用 ((…)) 作为判断语句,大于和小于可以直接使用 > 和 **<**。

if (( a > b )); then
    ...
fi

布尔运算符

下表列出了常用的布尔运算符,假定变量 a 为 10,变量 b 为 20:

运算符 说明 举例
! 非运算,表达式为 true 则返回 false,否则返回 true。 [ ! false ] 返回 true。
-o 或运算,有一个表达式为 true 则返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a 与运算,两个表达式都为 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。
  1. !(非运算符)的优先级最高。
  2. -a(与运算符)的优先级次之。
  3. -o(或运算符)的优先级最低

可以通过加()的方式改变运算优先级

例如

if [ ! -f "$file" ] -o ([ -d "$dir" ] -a [ -w "$dir" ]); then
    echo "File does not exist or (directory exists and is writable)."
fi

逻辑运算符

以下介绍 Shell 的逻辑运算符,假定变量 a 为 10,变量 b 为 20:

运算符 说明 举例
&& 逻辑的 AND [[ $a -lt 100 && $b -gt 100 ]] 返回 false
|| 逻辑的 OR [[ $a -lt 100 || $b -gt 100 ]] 返回 true

注意:逻辑运算是用在[[]]中的而布尔运算用在[]中,用法和之前的布尔运算符类似

补充知识点

在Shell脚本中,[ ](方括号)和[[ ]](双方括号)都用于条件测试,但它们之间存在一些重要的区别:

[ ](方括号)

  1. 兼容性[ ] 是 POSIX 标准的一部分,因此在所有遵循 POSIX 的 Shell 中都可用,包括 shbashksh 等。
  2. 语法限制[ ] 的语法较为简单,不支持复杂的字符串操作和模式匹配。
  3. 退出状态[ ] 命令执行完毕后会返回一个退出状态(0表示真,非0表示假)。
  4. 错误处理:如果 [ ] 内的表达式语法错误,它会产生一个非零退出状态,但不会报错。
  5. 使用test命令:在某些系统中,[ ] 实际上是一个名为 test 的命令的链接,因此也可以写作 test condition

[[ ]](双方括号)

  1. Bash 扩展[[ ]] 是 Bash 的扩展测试命令,提供了更多的功能和灵活性,但不是 POSIX 标准的一部分。因此,它只在支持 Bash 扩展的 Shell 中可用。
  2. 字符串操作[[ ]] 支持使用 ==!= 进行字符串比较,而 [ ] 只能使用 =!=
  3. 模式匹配[[ ]] 支持使用 Shell 的模式匹配符号(如 *?[...])进行字符串匹配。
  4. 正则表达式[[ ]] 支持使用 =~ 进行正则表达式匹配。
  5. 优先级:在 [[ ]] 中,逻辑运算符 &&|| 的优先级高于比较运算符,而在 [ ] 中,所有运算符的优先级是相同的。
  6. 错误处理:如果 [[ ]] 内的表达式语法错误,Bash 会报错并显示错误信息。
  7. 退出状态:与 [ ] 类似,[[ ]] 命令执行完毕后也会返回一个退出状态。

字符串运算符

下表列出了常用的字符串运算符,假定变量 a 为 “abc”,变量 b 为 “efg”:

运算符 说明 举例
= 检测两个字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
!= 检测两个字符串是否不相等,不相等返回 true。 [ $a != $b ] 返回 true。
-z 检测字符串长度是否为0,为0返回 true。 [ -z $a ] 返回 false。
-n 检测字符串长度是否不为 0,不为 0 返回 true。 [ -n “$a” ] 返回 true。
$ 检测字符串是否不为空,不为空返回 true。 [ $a ] 返回 true。
a='hello'
b='world'

if [ $a = $b ]
then
  echo 'a = b'
fi

if [ $a != $b ]
then
  echo 'a != b'
fi

if [ -z $a ]
then
  echo '字符串a长度为0'
fi

if [ -n $a ]
then
  echo '字符串a长度不为0'
fi

if [ $a ]
then
 echo '字符串不为空'
fi

文件测试运算符

文件测试运算符用于检测 Unix 文件的各种属性。

属性检测描述如下:

操作符 说明 举例
-b file 检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。
-c file 检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $file ] 返回 false。
-d file 检测文件是否是目录,如果是,则返回 true。 [ -d $file ] 返回 false。
-f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ] 返回 true。
-g file 检测文件是否设置了 SGID 位,如果是,则返回 true。 [ -g $file ] 返回 false。
-k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 [ -k $file ] 返回 false。
-p file 检测文件是否是有名管道,如果是,则返回 true。 [ -p $file ] 返回 false。
-u file 检测文件是否设置了 SUID 位,如果是,则返回 true。 [ -u $file ] 返回 false。
-r file 检测文件是否可读,如果是,则返回 true。 [ -r $file ] 返回 true。
-w file 检测文件是否可写,如果是,则返回 true。 [ -w $file ] 返回 true。
-x file 检测文件是否可执行,如果是,则返回 true。 [ -x $file ] 返回 true。
-s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true。
-e file 检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ] 返回 true。

其他检查符:

  • -S: 判断某文件是否 socket。
  • -L: 检测文件是否存在并且是一个符号链接。

流程控制

if

if condition1
then
    command1
elif condition2
then
    command2
else
    command3
fi

case

echo '输入 1 到 4 之间的数字:'
read num
case $num in
    1) echo '你选择了1'
    ;;
    2) echo '你选择了2'
    ;;
    3) echo '你选择了3'
    ;;
    4) echo '你选择了4'
    ;;
    *) echo '你没有输入1到4之间的数字'
    ;;
esac

for

for循环使用变量名获取列表中的当前取值

for loop in 1 2 3 4 5
do
    echo "The value is: $loop"
done

while

while 循环用于不断执行一系列命令,也用于从输入文件中读取数据。其语法格式为:

#!/bin/bash
i=1
while(( $i<=5 ))
do
    echo $i
    let "i++"
done

let是用于实现类似c++中自增1的命令

break和continue

#!/bin/bash
i=1
while(( $i<=5 ))
do
    echo $i
    let "i++"
    if (( $i>=3 ))
    then
      break
    fi
done

continue用于跳过本次循环,break用于退出循环

函数

函数通过$1,$2来接受传参,如果超过10个参数则使用${10}这样来接受第十个参数,调用完函数后使用$?来获取上一个函数的返回值

注意:$?取值不能超过255,否则会取其模上256

func(){
a=$1
b=$2
result=1
i=0
while (( i<b ))
do
  result=$((result*a))
  ((i++))
done
echo "return is $result"
return $result
}


#调用函数
func 2 3
echo "func 2 3运算结果为 $?"

return is 8

func 2 3运算结果为8

exit关键字用于返回状态码,如果成功则返回0,失败返回其它状态码

另外,还有几个特殊字符用来处理参数:

参数处理 说明
$# 传递到脚本或函数的参数个数
$* 以一个单字符串显示所有向脚本传递的参数
$$ 脚本运行的当前进程ID号
$! 后台运行的最后一个进程的ID号
$@ 与$*相同,但是使用时加引号,并在引号中返回每个参数。
$- 显示Shell使用的当前选项,与set命令功能相同。
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

案例

func(){
        timeout=5
        success=0
        #失败次数
        fails=0
        while true
           do
             wget www.baidu.com --timeout=${timeout} --tries=1 -q -O /etc/null


             if [ $? -ne 0 ]
               then
                 let fails=fails+1
             else
                 let success++
             fi

             if ((success >= 1))
               then
                 echo "恭喜你,该网站正在健康运作"
                 break
             fi

             if ((fails >= 2))
               then
                 echo "该网站出现了异常"
                 break
             fi
           done
  return
}

func
exit 0

检查网站是否健康的一个简单shell脚本


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以邮件至 1300452403@qq.com

文章标题:Shell脚本基础

字数:3.4k

本文作者:Os467

发布时间:2024-12-18, 23:30:10

最后更新:2024-12-19, 00:27:51

原始链接:https://os467.github.io/2024/12/18/Shell%E8%84%9A%E6%9C%AC%E5%9F%BA%E7%A1%80/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

×

喜欢就点赞,疼爱就打赏