3-轻松学会 shell 脚本

教程 薪牛 ⋅ 于 2023-01-05 15:24:25 ⋅ 958 阅读

1 第一个shell脚本

在root家目录下创建shell目录,在shell目录下创建一个hello.sh 文件,文件内容如下:

#! /bin/bash
# 输出hello world
echo "hello world!"

其中:

第一行:#! 开头,指定脚本的运行环境。

第二行:#开头,养成良好的注释习惯,这里一般说明脚本功能、作者、修改历史等等

echo ,把其参数传递给标准输出。

执行脚本需要 hello.sh 文件有执行权限,设置hello.sh 文件的执行权限

chmod a+x hello.sh

执行hello.sh文件脚本

# sh :即使没有执行权也可以执行
sh hello.sh

#路径方式:可以采用绝对路径或相对路径
#注意:拥有执行权才可以执行
./hello.sh
/root/shell/hello.sh

示例:

[root@localhost ~]# mkdir shell
[root@localhost ~]# cd shell
[root@localhost shell]# vim hello.sh
#! /bin/bash
# 输出hello world
echo "hello world!"
~                 
"hello.sh" [新] 3L, 52C 已写入                                                                       
[root@localhost shell]# ll
总用量 4
-rw-r--r--. 1 root root 52 8月  13 19:53 hello.sh
# 不加执行权也能运行
[root@localhost shell]# sh hello.sh
hello world!
# 目录方式必须加执行权
[root@localhost shell]# ./hello.sh
-bash: ./hello.sh: 权限不够
# 给所有用户组都加了执行权
[root@localhost shell]# chmod a+x hello.sh
# 相对路径运行
[root@localhost shell]# ./hello.sh
hello world!
[root@localhost shell]# pwd
/root/shell
# 绝对路径运行
[root@localhost shell]# /root/shell/hello.sh
hello world!

2 变量

2.1 变量赋值和使用

#! /bin/bash
# 将一个变量赋给str
str="monday"
echo "today is: $str"
echo ${str}

其中:

1)变量名首字符必须为字母,名字只能用字母、数字、下滑线,不要用bash关键字。非法的名字:8var、var-8

2)变量定义或赋值时,变量名与值之间用等号连接:变量名=值,等号两边不能有空格,值中有空格或特殊字符需要用双引号或单引号引起来。

3)使用 $变量名 或 ${变量名} 形式获取变量值,这两种方式没有什么区别,但推荐用${}方式。

如何调试 shell 脚本?

命令格式:sh -x shell脚本名称

功能:将脚本的每个步骤都执行一遍并输出到屏幕,利于调试代码。

[root@localhost shell]# vim s1.sh
#! /bin/bash
#将一个变量赋给str
str="monday"
echo "today is: $str"
echo ${str}
~                                                                     
"s1.sh" [新] 6L, 87C 已写入          
# 调试脚本:正常执行
[root@localhost shell]# sh -x s1.sh 
+ str=monday
+ echo 'today is: monday'
today is: monday
+ echo monday
monday
[root@localhost shell]# 
# 故意把脚本修改错 echo --> eho
[root@localhost shell]# vim s1.sh
#! /bin/bash
#将一个变量赋给str
str="monday"
eho "today is: $str"
echo ${str}
~                                                                                        
"s1.sh" 6L, 86C 已写入             
# 调试脚本报错,根据报错定位脚本错误位置
[root@localhost shell]# sh -x s1.sh 
+ str=monday
+ eho 'today is: monday'
s1.sh:行5: eho: 未找到命令
+ echo monday
monday
[root@localhost shell]# 

2.2 变量替换

美元符号$ ,如果想输出$ 符号,则要用“\” 进行转义。

示例:

s2.sh 文件内容如下

#! /bin/bash
str="100"
echo "人民币: ¥${str}"
echo "美元: \$ ${str}"

2.3 位置变量

想要给脚本中传递参数,在脚本中接收参数可以使用$1....$n的方式

示例:

[root@localhost shell]# vim s3.sh
#! /bin/bash
# $0:脚本的名称
echo \$0: $0
# $1:第1个入参
echo \$1: $1
# $4:第4个入参
echo \$4: $4
# $#:脚本入参个数
echo \$#: $#
# $*:所有参数组成一个字符串
echo \$*: $*
# $@:每个位置参数是一个字符串
echo \$@: $@
# $?:上个命令的返回值,0:执行成功;非0:执行失败
echo \$?: $?
# $$:当前进程id
echo \$$: $$
# 命令执行失败
cho "hehe"
# 返回非0
echo \$?: $?

执行结果:

file

2.4 bush 引号规则

1)单引号'':单引号里面的所有字符都是普通字符。

2)双引号"":双引号会保留变量特性,用值替换。

3)倒引号``:位于Esc 键下方,用倒引号括起一个命令时,这个命令将会被执行,执行后的结果作为这个表达式的值。

示例:

[root@localhost shell]# vim s4.sh
#! /bin/bash
name=hehe
# 全是普通字符串
echo '$name'
# name可替换
echo "$name"
# 将date命令的结果输出
echo `date`

运行结果:

file

3 数组

3.1 定义数组

1)常量列表的方式

# 括号内的元素用空格分隔
arr1=("a1" "b1" "c1")

2)declare 命令定义数组

# 定义数据arr2,并初始化元素
declare -a arr2=("a2" "b2" "c2")

# 先定义,后给元素赋值
declare -a arr3
arr3[0]="a3"
arr3[1]="b3"
arr3[2]="c3"

3.2 使用数组

1)获取数组长度

​ 用${#数组名[@或*]} 可以得到数组长度

​ ${#arr[*]} 或 ${#arr[@]}

2)读取数组元素:

​ 读取下标为1的元素:${arr[1]}

​ 读取数组整个元素:${arr[*]}

3)给数组元素赋值:

​ arr[1]=1

4)删除数组元素:

​ 删除后,数组长度改变

​ unset arr[1]

​ ${#arr[*]}

示例:

[root@localhost shell]# arr1=("a1" "b1" "c1")
[root@localhost shell]# echo ${arr1[*]}
a1 b1 c1
[root@localhost shell]# declare -a arr2=("a2" "b2" "c2")
[root@localhost shell]# echo ${arr2[*]}
a2 b2 c2
[root@localhost shell]# declare -a arr3
[root@localhost shell]# arr3[0]="a3"
[root@localhost shell]# arr3[1]="b3"
[root@localhost shell]# arr3[2]="c3"
[root@localhost shell]# echo ${arr3[*]}
a3 b3 c3
[root@localhost shell]# 
# 查看数组长度
[root@localhost shell]# echo ${#arr3[*]}
3
# 获取数组第一个元素
[root@localhost shell]# echo ${arr3[0]}
a3
# 删除数组第一个元素,数组长度-1
[root@localhost shell]# unset arr3[0]
[root@localhost shell]# echo ${#arr3[*]}
2
[root@localhost shell]# echo ${arr3[*]}
b3 c3

4 运算符

4.1 比较运算符

4.1.1 数字比较

运算符 说明 示例
-eq 等于 [ 1 -eq 1 ] && echo 'ok'
-ne 不等于 [ 1 -ne 2 ] && echo 'ok'
-lt 小于 [ 1 -lt 2 ] && echo 'ok'
-gt 大于 [ 1 -gt 0 ] && echo 'ok'
-le 小于等于 [ 1 -le 1 ] && echo 'ok'
-ge 大于等于 [ 1 -ge 1 ] && echo 'ok'

注意:

​ []内部写的时候,要用空格隔开。

[root@localhost shell]# [ 1 -eq 1 ] && echo 'ok'
ok
[root@localhost shell]# [ 1 -lt 0 ] && echo 'ok'   
[root@localhost shell]# [ 1 -lt 2 ] && echo 'ok' 
ok
# 没有空格隔开,报错
[root@localhost shell]# [ 1 -lt 2] && echo 'ok' 
-bash: [: 缺少 ]
# 变量替换也可以
[root@localhost shell]# a=1
[root@localhost shell]# [ $a -lt 2 ] && echo 'ok' 
ok
[root@localhost shell]# 

4.1.2 字符串比较

运算符 说明 示例
== 比较两个字符串是否相等,相等返回true [ "aaa" == "aaa" ] && echo 'ok'
!= 比较两个字符串是否不相等,不相等返回true [ "aaa" != "bbb" ] && echo 'ok'

注意:

​ []内部写的时候,要用空格隔开。

示例:

[root@localhost shell]# [ "aaa" == "aaa" ] && echo 'ok'
ok
[root@localhost shell]# 
[root@localhost shell]# [ "aaa" != "bbb" ] && echo 'ok'    
ok
# 字符串判空
[root@localhost shell]# s=aaa
# 字符串非空
[root@localhost shell]# [ "${s}x" == "x" ] && echo 'ok'         
[root@localhost shell]# 
# 字符串为空
[root@localhost shell]# s=""
[root@localhost shell]# [ "${s}x" == "x" ] && echo 'ok'
ok

4.2 逻辑运算符

运算符 说明 示例
! 非运算 [ ! 2 -lt 1 ] && echo 'ok'
-o 或运算 [ 1 -eq 1 -o 1 -eq 2 ] && echo 'ok'
-a 与运算 [ 1 -eq 1 -a 2 -eq 2 ] && echo 'ok'
&& 短路与运算,在[]表达式内不能用,在[]表达式间可用 [ 1 -eq 1 -a 2 -eq 2 ] && echo 'ok'
|| 短路或运算,在[]表达式内不能用,在[]表达式间可用 [ 1 -ne 1 ] || echo 'ok'

注意:

​ []内部写的时候,要用空格隔开。

示例:

[root@localhost shell]# [ ! 2 -lt 1 ] && echo 'ok' 
ok
[root@localhost shell]# [ 1 -eq 1 -o 1 -eq 2 ] && echo 'ok' 
ok
[root@localhost shell]# [ 1 -eq 1 -a 2 -eq 2 ] && echo 'ok'   
ok
[root@localhost shell]# [ 1 -eq 1 -a 2 -ne 2 ] && echo 'ok'  
[root@localhost shell]# [ 1 -ne 1 ] || echo 'ok'
ok

4.3 文件运算符

-b file 检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。
-c file 检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $file ] 返回 false。
-d file 检测文件是否是目录,如果是,则返回 true。 [ -d $file ] 返回 false。
-f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ] 返回 true。
-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。

示例:

[root@localhost shell]# [ -e hello.sh ] && echo 'ok'        
ok
[root@localhost shell]# [ -f hello.sh ] && echo 'ok'
ok
[root@localhost shell]# [ -d hello.sh ] && echo 'ok'      
[root@localhost shell]# 

5 if 分支语句

5.1 if语句

语法:

if  条件表达式一 ; then   
    表达式一true时执行这里
#[
elif  条件判断式二 ; then    
    表达式二true时执行这里
elif  条件判断式三 ; then    
    表达式三true时执行这里
else    
    都不成立时,执行这里
#]
fi

其中:

​ [] 内的是可选。

示例:

需求:实现根据脚本入参判断是start、stop、restart,然后输出相应操作;否则输出Other操作

[root@localhost shell]# vim s5.sh
#! /bin/bash
cmd=$1
if [ $cmd == "start" ]; then
        echo "start operation"
elif [ $cmd == "stop" ]; then
        echo "stop operation"
elif [ $cmd == "restart" ]; then
        echo "restart operation"
else
        echo "other operation"
fi

6 模式匹配:case

case $var in
     模式1)  
             代码块1
             ;; 
     模式2)    
             代码块2    
             ;;    
     模式3)    
             代码块3   
             ;;    
        *)    
             代码块4    
             ;;
esac

示例:

需求:把上面if需求的代码用case实现

[root@localhost shell]# vim s6.sh 
#! /bin/bash
cmd=$1
case $cmd in
        "start") echo "start operation"
                ;;
        "stop") echo "stop operation"
                ;;
        "restart") echo "restart operation"
                ;;
        *) echo "other operation"
                ;;
esac

7 for循环语句

7.1 for 循环变量 in 数据列表

语法:

for 循环变量 in 数据列表
do
    循环体代码段
done

其中:

​ 这里的数据列表 是一系列以空格分隔的值,shell每次从这个列表中取出一个值,然后运行do/done 之间的命令。

示例:

需求:输出指定目录(脚本入参)下文档是文件类型的文档

[root@localhost shell]# vim s7.sh 
#! /bin/bash
# 获取输入参数
base_path=$*
# 将目录下的列表用括号括起来变成数组
arr=(`ls $base_path`)
# 遍历数组的每个元素(文档)
for f in ${arr[*]}
do
        # 判断是否是文件
        if [ -f $f ]; then
                echo "$f is file"
        fi
done

运行结果:

file

7.2 for (( 控制变量的初始化; 循环的条件; 循环控制变量的更新 ))

语法:

#满足条件则循环否则退出
for (( 控制变量的初始化; 循环的条件; 循环控制变量的更新 )) 
do
     循环体代码段
done

示例:

1)计算从1加到10的结果;统计偶数的个数

[root@localhost shell]$ vim s8.sh 
#! /bin/bash
sum=0
count=0
for((i=1;i<=10;i++))
do
        # 求和
        sum=$((sum+i))
        # 统计偶数的个数
        if [ $((i%2)) -eq 0 ]; then
                ((count++))
        fi
done

echo sum:${sum}, count:${count}

8 函数定义

8.1 定义一个没有返回值的函数

#!/bin/bash
fun(){
    echo "hello student!"
}
echo "-----函数开始执行-----"
fun
echo "-----函数执行完毕-----"

执行结果

file

8.2 定义一个带有返回值的函数

#!/bin/bash
num1=$1
num2=$2
funandReturn(){
    return $(($num1+$num2))
}
funandReturn
echo "输入的两个数字之和为 $? !"

执行结果:

file

版权声明:原创作品,允许转载,转载时务必以超链接的形式表明出处和作者信息。否则将追究法律责任。来自海汼部落-薪牛,http://hainiubl.com/topics/75977
回复数量: 0
    暂无评论~~
    • 请注意单词拼写,以及中英文排版,参考此页
    • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
    • 支持表情,可用Emoji的自动补全, 在输入的时候只需要 ":" 就可以自动提示了 :metal: :point_right: 表情列表 :star: :sparkles:
    • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif,教程
    • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
    Ctrl+Enter