shell就是人机交互的一个桥梁 ;shell 本质上是 linux 命令,一条一条命令组合在一起,实现某一个目的,就变成了shell脚本。它从一定程度上 减轻了工作量,提高了工作效率。
官方概念:
Shell 通过提示您输入,向操作系统解释该输入,然后处理来自操作系统的任何结果输出,简单来说Shell就是一个用户跟操作系统之间的一个命令解释器。
.sh
#!/bin/bash
做为首行来指定解释器[root@node100 shell_test]# vim HelloWorld.sh
编写内容
- #!/bin/bash
- echo 'Hello World!!!'
- # echo 为打印输出
执行脚本文件
① 给文件执行权限
[root@node100 shell_test]# chmod +x HelloWorld.sh
②执行脚本
- # 相对路径执行
- [root@node100 shell_test]# ./HelloWorld.sh
-
- # 绝对路径执行
- [root@node100 shell_test]# /shell_test/HelloWorld.sh
注意:bash中的引号
双引号"" :会把引号的内容当成整体来看待,允许通过$符号引用其他变量值
单引号'' :会把引号的内容当成整体来看待,禁止引用其他变量值,shell中特殊符号都被视为普通字符
反撇号`` :反撇号和$()一样,引号或括号里的命令会优先执行,如果存在嵌套,反撇号不能用
在编译过程中被解释器忽略的内容就称为注释。
单行注释
- 单行注释格式:
- # 这是一个注释
多行注释
- 多行注释格式:
- :<<EOF
- 注释内容...
- 注释内容...
- 注释内容...
- EOF
- 说明:EOF 也可以使用其他符号
变量是用来临时保存数据的,该数据是可以变化的数据。
定义语法:变量名=变量值
①定义变量
[root@node100 shell_test]# a=123
②调用变量
- [root@node100 shell_test]# echo $a
- 或者
- [root@node100 shell_test]# echo ${a}
③删除变量
[root@node100 shell_test]# unset a
以上变量用法在Shell脚本中也同样使用
①变量名区分大小写
②变量名不能有特殊符号
特别说明:对于有空格的字符串给变量赋值时,要用引号引起来;
③变量名不能以数字开头但可以包含数字
④等号两边不能有任何空格
⑤变量名尽量做到见名知意
①直接赋值给一个变量
- [root@node100 shell_test]# a=123456789
- [root@node100 shell_test]# echo ${a:2:3} # 表示从第3位开始截取,截取3个字符
- 345
说明:
$变量名
和${变量名}
的异同
相同点:相同点:都可以调用变量
不同点:${变量名}可以只截取变量的一部分,而$变量名不可以
②命令执行结果赋值给变量
- [root@node100 shell_test]# a=`hostname`
- [root@node100 shell_test]# echo $a
- node100
- [root@node100 shell_test]# b=$(date)
- [root@node100 shell_test]# echo $b
- 2022年 07月 30日 星期六 13:59:22 KST
③交互式定义变量(read)
目的:让用户自己给变量赋值,比较灵活。
语法:read [选项] 变量名
常见选项
选项 | 解释 |
---|---|
-p | 定义提示用户的信息 |
-n | 定义字符数(现在变量长度) |
-s | 不显示(不显示用户的密码) |
-t | 定义超时时间,默认单位为秒(现在用户输入变量值的超时时间,单位为秒) |
举例1:让用户自己定义变量值
[root@node100 shell_test]# read -p "请输入你的名字" name
[root@node100 shell_test]# read -n6 a
[root@node100 shell_test]# read -s pwd
[root@node100 shell_test]# read -t1 a
举例2:变量值来自文件
注意:无论文件有多少内容,默认只取第一行内容作为变量值。
④定义有类型的变量(declare)
目的:给变量做一些限制,固定变量的类型,比如:整型、只读
用法:declare 选项 变量名=变量值
常用选项:
选项 | 解释 | 举例 |
---|---|---|
-i | 将变量看成整数 | declare -i A=123 |
-r | 定义只读变量 | declare -r B=hello |
-a | 定义普通数组;查看普通数组 | |
-A | 定义关联数组;查看关联数组 | |
-x | 将变量通过环境导出 | declare -x A=123456 等于 export A=123456 |
举例:
凡是被-i
选项修饰的变量,只能赋值整数。
凡是被-r
选项修饰的变量,为只读变量不能修改。
系统变量(内置bash中变量) : shell本身已经固定好了它的名字和作用.
内置变量 | 含义 |
---|---|
$? | 返回上一条命令的执行状态;0表示执行正常,非0表示执行异常或错误 |
$0 | 当前执行的程序和脚本名 |
$# | 脚本后面接的参数的个数 |
$* | 脚本后面所有参数,参数当成一个整体输出,每一个变量参数之间以空格隔开 |
$@ | 脚本后面所有参数,参数是独立的,也是全部输出 |
$1-$9 | 脚本后面的位置参数,$1 表示第一个位置参数,以此类推 |
${10}-${n} | 扩展位置参数,第10个位置变量必须用{}大括号括起来(2位数字以上括起来) |
$$ | 先前所在进程的进程号 |
$! | 后台运行的最后一个进程号 |
!$ | 调用最后一条命令历史中的参数 |
求变量长度:${#变量名}
- [root@node100 shell_test]# q=123
- [root@node100 shell_test]# echo ${#q}
替换:${变量/old/new}
将变量中第一次出现的old值替换成new值
- [root@node100 shell_test]# url=www.baidu.com
- [root@node100 shell_test]# echo ${url/w/x}
替换:${变量//old/new}
将变量中出现的old值全部替换成new值
[root@node100 shell_test]# echo ${url//w/x}
算术运算:默认情况下,shell就只能支持简单的整数运算
运算内容:加(+)、减(-)、乘(*)、除(/)、求余数(%)
表达式 | 举例 |
---|---|
$(()) | echo $((1+1)) |
$[] | echo $[10-5] |
expr | expr 10 / 5 |
let | n=1;let n+=1 等价于let n=n+1 |
注意:在使用expr
时一定要注意空格,而且在做乘法运算时一定要加引号,因为*
在Linux中表示通配符。
①$(())
②$[]
③expr
④let
i++
和++i
i++:先打印i,后进行加1操作
++i:先进行加1操作,后打印i
注意:除了i++
和++i
外,i--
和--i
;expr不支持i++
和++i
①一次赋予一个值
数组名[索引下标]=值
- [root@node100 shell_test]# qwe[0]=1
- [root@node100 shell_test]# qwe[1]=2
- [root@node100 shell_test]# qwe[2]=3
访问:${数组名[元素下标]}
[root@node100 shell_test]# echo ${qwe[0]}
也可以通过declare -a 数组名
的方式去声明数组
②一次赋予多个值
数组名=(值1 值2 值3 ...)
[root@node100 shell_test]# asd=(v1 v2 v3)
访问:${数组名[元素下标]}
[root@node100 shell_test]# echo ${asd[0]}
③将文件中每一行赋值给数组
- [root@node100 shell_test]# cat 1.txt
- qwe
- asd
- zxc
- rty
- [root@node100 shell_test]# zxc=(`cat 1.txt`)
访问:${数组名[元素下标]}
[root@node100 shell_test]# echo ${zxc[0]}
①声明关联数组
声明方式:declare -A 数组名
[root@node100 shell_test]# declare -A array
②数组赋值
一次赋一个值
语法:数组名[索引or下标]=变量值
[root@node100 shell_test]# array[hello]=world
访问数组中的值
语法:echo ${数组名[索引or下标]}
一次赋多个值
语法:数组名=([下标1]=变量值1 [小标2]=变量值2 ... ...)
- [root@node100 shell_test]# declare -A array2
- [root@node100 shell_test]# array2=([1]=one [name]=tom [age]=18)
访问
语法:echo ${数组名[索引or下标]}
[root@node100 shell_test]# echo ${array2[1]}
访问数组中全部数据
[root@node100 shell_test]# echo ${array2[*]}
访问数组中的全部下标或索引名词
[root@node100 shell_test]# echo ${!array2[*]}
格式1: test 条件表达式
格式2: [ 条件表达式 ]
格式3: [[ 条件表达式 ]]
可以判断文件类型,判断文件新旧,判断字符串是否相等,判断权限等等..
①判断文件类型
判断参数 | 含义 |
---|---|
-e | 判断文件是否存在 |
-f | 判断文件是否存在并且是一个普通文件 |
-d | 判断文件是否存在并且是一个目录 |
-L | 判断文件是否存在并且是一个软连接文件 |
-b | 判断文件是否存在并且是一个块设备文件 |
-S | 判断文件是否存在并且是一个套接字文件 |
-c | 判断文件是否存在并且是一个字符设备文件 |
-p | 判断文件是否存在并且是一个命名管道文件 |
-s | 判断文件是否存在并且是一个非空文件(有内容) |
举例:test 条件表达式
- [root@node100 shell_test]# test -e a
- [root@node100 shell_test]# echo $?
举例:[ 条件表达式 ]
- [root@node100 shell_test]# [ -e 1.txt ]
- [root@node100 shell_test]# echo $?
举例:[[ 条件表达式 ]]
- [root@node100 shell_test]# [[ -e 1.txt ]]
- [root@node100 shell_test]# echo $?
②判断文件权限
判断参数 | 含义 |
---|---|
-r | 当前用户对其是否可读 |
-w | 当前用户对其是否可写 |
-x | 当前用户对其是否可执行 |
-u | 是否有suid,高级权限冒险位 |
-g | 是否有sgid,高级权限强制位 |
-k | 是否有t位,高级权限粘滞位 |
举例:
- [root@node100 shell_test]# [ -r 1.txt ]
- [root@node100 shell_test]# echo $?
- [root@node100 shell_test]# [ -x 1.txt ]
- [root@node100 shell_test]# echo $?
③判断文件新旧
说明:这里的新旧指的是文件的修改时间。
判断参数 | 含义 |
---|---|
file1 -nt file2 | 比较file1是否比file2新 |
file1 -ot file2 | 比较file1是否比file2旧 |
file1 -ef file2 | 比较是否为同一个文件 |
举例:
- [root@node100 shell_test]# [ 1.txt -nt demo1.sh ]
- [root@node100 shell_test]# echo $?
④判断整数
判断参数 | 含义 |
---|---|
-eq | 相等 |
-ne | 不等 |
-gt | 大于 |
-lt | 小于 |
-ge | 大于等于 |
-le | 小于等于 |
举例:
- [root@node100 shell_test]# [ 1 -eq 1 ]
- [root@node100 shell_test]# echo $?
⑤判断字符串
判断参数 | 含义 |
---|---|
-z | 判断是否为空字符串,字符串长度为0则成立 |
-n | 判断是否为非空字符串,字符串长度不为0则成立 |
string1 = string2 | 判断字符串是否相等 |
string1 != string2 | 判断字符串是否不相等 |
举例:
- [root@node100 shell_test]# [ a = a ]
- [root@node100 shell_test]# echo $?
⑥多重条件判断
判断符号 | 含义 | 举例 |
---|---|---|
-a和&& | 逻辑与 | [ 1 -eq 1 -a 1 -ne 0 ] 或者[ 1 -eq 1 ] && [ 1 -ne 0 ] |
-o | 逻辑或 | [ 1 -eq 1 -o 1 -ne 0 ] |
特别说明:
&& 前面的表达式为真,才会执行后面的代码
|| 前面的表达式为假,才会执行后面的代码
[root@node100 shell_test]# [ 2 -eq 2 ] && echo 'true'
[root@node100 shell_test]# [ 2 -eq 1 ] && echo 'true'||echo 'false'
注意:在(( ))中,=表示赋值;==表示判断
举例:
注意:;
只用于分割命令或表达式
语法结构:
① if结构
- if condition
- then
- command1
- command2
- ...
- commandN
- fi
② if...else结构
- if condition
- then
- command1
- command2
- ...
- commandN
- else
- command
- fi
③ if...elif...else结构
- if condition1
- then
- command1
- elif condition2
- then
- command2
- else
- commandN
- fi
举例:
编写if.sh
文件
- #!/bin/bash
- read -p "请输入你的年龄" age
- if [ $age -ge 1 -a $age -le 18 ]
- then
- echo "年龄大于等于1并且小于等于18是未成年人"
- elif [[ $age -gt 18 ]]
- then
- echo "年龄大于18是成年人"
- else
- echo "请输入正确的年龄"
- fi
执行if.sh
文件
- [root@node100 shell_test]# chmod +x if.sh
- [root@node100 shell_test]# ./if.sh
语法结构
- case 变量名 in
- 变量值1)
- command1 需要执行的语句
- ;; 两个分号代表命令结束
- 变量值2)
- command2
- ;;
- 变量值3)
- command3
- ;;
- *) default,不满足以上模式,默认执行*)下面的语句
- command4
- ;;
- esac
举例:
编写case.sh
文件
- #!/bin/bash
- read -p "请输入变量值" i
- case $i in
- 1)
- echo "你是第一名"
- ;;
- 2)
- echo "你是第二名"
- ;;
- 3)
- echo "你是第三名"
- ;;
- *)
- echo "你不是前三名"
- ;;
- esac
执行
- [root@node100 shell_test]# chmod +x case.sh
- [root@node100 shell_test]# ./case.sh
语法结构:
①列表循环
- 列表for循环:用于将一组命令执行已知的次数
- 基本语法格式
- for variable in {list}
- do
- command
- command
- …
- done
- 或者
- for variable in a b c
- do
- command
- command
- done
举例(控制台):
[root@node100 shell_test]# for i in {1..10};do echo $i;done
[root@node100 shell_test]# for i in 1 2 3;do echo $i;done
\
- [root@node100 shell_test]# for i in {1..10..2};do echo $i;done
- # {起始值..结束值..步长}
[root@node100 shell_test]# for i in {10..1..2};do echo $i;done
- [root@node100 shell_test]# for i in $(seq 10);do echo $i;done
- # seq是个命令 seq [起始值] [步长] [结束值]
②不带列表循环
- for variable
- do
- command
- command
- …
- done
举例:
编写for1.sh
- #!/bin/bash
- for i
- do
- echo $i
- done
在执行的传参
- [root@node100 shell_test]# chmod +x for1.sh
- [root@node100 shell_test]# ./for1.sh 1 2 3
③类C风格的for循环
- for(( expr1;expr2;expr3 ))
- do
- command
- command
- …
- done
- # expr1:初始条件
- # expr2:循环条件
- # expr3:迭代条件
举例:
编写for2.sh
文件
- #!/bin/bash
- for((i=1;i<=5;i++))
- do
- echo $i
- done
执行
- [root@node100 shell_test]# chmod +x for2.sh
- [root@node100 shell_test]# ./for2.sh
特点:条件为真就进入循环;条件为假就退出循环
语法结构:
- while 表达式
- do
- command...
- done
举例:
编写while.sh
文件
- #!/bin/bash
- i=1
- while ((i<=5)) # ((i<=5)) 也可以换成 [ $i -le 5 ]
- do
- echo $i
- let i++
- done
执行
- [root@node100 shell_test]# chmod +x while.sh
- [root@node100 shell_test]# ./while.sh
特点:条件为假就进入循环;条件为真就退出循环
语法结构
- until expression
- do
- command
- command
- ...
- done
举例:
编写until.sh
文件
- #!/bin/bash
- i=1
- until [ $i -gt 5 ]
- do
- echo $i
- let i++
- done
执行
- [root@node100 shell_test]# chmod +x until.sh
- [root@node100 shell_test]# ./until.sh
6.6、循环控制语句
continue:继续;表示循环体内下面的代码不执行,重新开始下一次循环
break:打断;马上停止执行本次循环,执行循环体后面的代码
exit:表示直接跳出程序
举例:循环打印1-5,但不打印3
编写continue.sh
- #!/bin/bash
- for((i=1;i<=5;i++))
- do
- if ((i==3))
- then
- continue
- fi
-
- echo $i
- done
执行
- [root@node100 shell_test]# vim continue.sh
- [root@node100 shell_test]# ./continue.sh
举例:循环打印1-5,但是但是打印到3的时候结束循环
编写break.sh
文件
- #!/bin/bash
- for((i=1;i<=5;i++))
- do
- echo $i
- if ((i==3))
- then
- break
- fi
- done
-
- echo "程序结束"
执行
- [root@node100 shell_test]# chmod +x break.sh
- [root@node100 shell_test]# ./break.sh
举例:循环打印1-5,但是但是打印到3的时候结束整个程序
编写exit.sh
文件
- #!/bin/bash
- for((i=1;i<=5;i++))
- do
- echo $i
- if ((i==3))
- then
- exit
- fi
- done
- echo "结束程序"
执行
- [root@node100 shell_test]# vim exit.sh
- [root@node100 shell_test]# ./exit.sh
shell中允许将一组命令集合或语句形成一段可用代码,这些代码块称为shell函数,给这段代码起个名字称为函数名,后续可以直接调用该段代码的功能。
语法结构
- [ function ] 函数名(){
- 命令代码
- [ return [value]]
- # 在return后面写一个值(0-256) 然后通过 echo $? 查看状态值。
- # 若只写return则表示结束,return后面的代码将不会执行
- 命令代码
- }
举例:编写求输入参数和的函数
编写fun.sh
文件
- #!/bin/bash
- function get_sum(){
- sum=0
- for i in $@
- do
- let sum+=i
- done
- return $sum # 也可以直接 echo
- }
执行
- [root@node100 shell_test]# source fun.sh # 生效文件
- [root@node100 shell_test]# get_sum 1 2 3 # 调用函数并传参
- [root@node100 shell_test]# echo $? # 查看状态