文章目录
一:初识shell
shell的中文名字叫”贝壳“ ,听这名字就知道shell是一个将系统接口及底层内核硬件封装好的解释型应用程序,shell有两种意思,一种是编译语言,一种是解释器,解释shell风格的解释器(可写脚本运行,可执行交互命令)
1.1 运行shell的两种方式
1、交互式环境
每敲一条立即执行一条
不能永久保存代码
2、把shell命令写入文件中,该文件称之为脚本文件
bash 脚本文件的路径
[root@localhost ~]# vim 2.sh # 脚本文件里是完整的执行内容
bip=wwww.baidu.com
ping $bip
[root@localhost ~]# bash 2.sh
PING www.wshifen.com (45.113.192.101) 56(84) bytes of data.
64 bytes from 45.113.192.101 (45.113.192.101): icmp_seq=1 ttl=128 time=239
------------------------------------------
[root@localhost ~]# chmod +x 2.txt
[root@localhost ~]# ./2.txt
# 将次文件添加一个可执行权限,相当于重新开了一个子进程运行
-------------------------------------------
# 运行shell脚本经历的三个阶段
(1)先启动bash解释器
(2)bash解释器会将脚本文件的内容从硬盘读入内存
(3)bash解释器会解释执行刚刚读入内存的代码,识别语法
三 变量
1.1 变量
”量“ 就是事物的状态,在计算机中,变量是一种读取内存的机制,是为了让计算机像人一样记录事物变换的状态,当然存不是目的,目地是为了取出来的时候方便;在定义好变量后,下次直接使用变量名即可。
使用
先定义,后使用
语法
变量名 赋值符 变量值
x = 1
1.2 变量的作用域
交互式使用-----》自定义,仅在当前shell生效
[root@localhost ~]# x=1
[root@localhost ~]# echo $x # $取变量值
1
环境变量-------》在当前shell及子shell生效
# export xxx 将变量定义父子继承使用,新开的窗口需要重新定义
[root@localhost ~]# x=111
[root@localhost ~]# export x
[root@localhost ~]# bash
[root@localhost ~]# echo $x
111
-------------------------------------------
# 添加系统开机自启的配置文件/etc/profile
将 x=111
export x
# 写到文件最下面,开机自启,注意:新开的子shell或者新开窗口及su无效
命令
export x # 设置变量名x父子继承
set # 查看所有变量(包括自定变量和环境变量)
env # 查看环境变量
unset x # 删除变量
1.3 引号对变量的影响
“”:软引用,解释中间的内容
‘’:硬引用,显示中间的内容
``:取中间命令的运行结果
[root@www ~]# name="egon"
[root@www ~]# echo "hello $name"
hello egon
[root@www ~]# echo 'hello $name'
hello $name
[root@www ~]# date +%F
2021-04-09
[root@www ~]# x=`date +%F`
[root@www ~]# touch $x.txt
2021-04-09.txt
[root@www ~]# y=$(date +%F) # $()嵌套使用
[root@www ~]# touch ${y}.bak
[root@www ~]# ls
2021-04-09.bak
[root@www ~]# tar czf `date +%F`.tar.gz /opt/
tar: Removing leading `/' from member names
[root@www ~]# ls
2021-04-09.tar.gz
二:shell特殊字符·元字符
shell语法中的特殊字符,注意:元字符是解释器运行
-
`` 与$():取命令的结果
[root@localhost ~]# echo `pwd` /root [root@localhost ~]# echo $(pwd) /root 不一样的地方在于$()可以嵌套,而``不能嵌套 [root@localhost ~]# echo $(ls $(find ./ -name "*.txt")) ./1a.txt ./1b.txt ./1c.txt ./1p.txt ./1q.txt ./1r.txt ./1s.txt ./1t.txt ./1.txt ./2021-04-09.txt ./2a.txt ./2b.txt ./2c.txt ./2.txt ./3a.txt ./3b.txt ./3c.txt ./3.txt .
-
~家目录
-
.与…
-
!取反
[root@localhost ~]# touch /test/{1.txt,2.txt,a.txt,aaa_bbb.txt} [root@localhost ~]# find /test ! -name 1.txt /test /test/2.txt /test/a.txt /test/aaa_bbb.txt [root@localhost ~]# ls /test/[!0-9].txt # .txt前只有一个字符,但是非数字 /test/a.txt [root@localhost ~]# ls /test/[^0-9].txt # .txt前只有一个字符,但是非数字 /test/a.txt
-
@无特殊$取变量值
-
#注释
-
$取变量值
[root@localhost ~]# x=1 [root@localhost ~]# echo $x 1
-
%、-、+运算符
# 数学运算 # 1、bc是比较常用的linux计算工具了,而且支持浮点运算: [root@localhost ~]# res=`echo 1+1 | bc` [root@localhost ~]# echo $res 2 [root@localhost ~]# res=`echo 10 % 3 | bc` [root@localhost ~]# echo $res 1 [root@localhost ~]# res=`echo 1.2+1.3|bc` [root@localhost ~]# echo $res 2.5 [root@localhost ~]# res=`echo 5.0+3.0|bc` [root@localhost ~]# echo $res 8.0 [root@localhost ~]# res=`echo "scale=2;5.0/3.0"|bc` [root@localhost ~]# echo $res 1.66 [root@localhost ~]# res=`echo "scale=2;5.0/6.0"|bc` [root@localhost ~]# echo $res .83 # 2、expr不支持浮点数计算。而且要注意数字与运算符中的空格 [root@localhost ~]# res=`expr 5 / 3` # 不支持浮点计算 [root@localhost ~]# echo $res 1 [root@localhost ~]# res=`expr 1+1` # 注意:要有空格 [root@localhost ~]# echo $res 1+1 [root@localhost ~]# res=`expr 1 + 1` [root@localhost ~]# echo $res 2 # 3、$(()) 同expr,不支持浮点数运算 [root@localhost ~]# echo $((1+1)) 2 [root@localhost ~]# echo $((1.0+2.0)) -bash: 1.0+2.0: 语法错误: 无效的算术运算符 (错误符号是 ".0+2.0") #4、let 不支持浮点数运算,而且不支持直接输出,只能赋值 [root@localhost ~]# let res=1+1 [root@localhost ~]# echo $res 2 [root@localhost ~]# [root@localhost ~]# let res=50/5 [root@localhost ~]# echo $res 10 [root@localhost ~]# let c=1.3*3 -bash: let: c=1.3*3: 语法错误: 无效的算术运算符 (错误符号是 ".3*3"
-
^同!一样
-
*任意多个字符
[root@localhost ~]# touch 1.txt 2.txt aa.txt aaa.txt [root@localhost ~]# rm -rf *.txt [root@localhost ~]# touch 1.txt 2.txt aa.txt aaa.txt a1c.txt [root@localhost ~]# ls *.txt 1.txt 2.txt a1c.txt aaa.txt aa.txt
-
()在子shell中执行
[root@localhost ~]# (x=1) [root@localhost ~]# echo $x 应用 [root@localhost ~]# (umask 066;touch a.txt) # umask的设置只在子shell中有效 [root@localhost ~]# ll a.txt -rw-------. 1 root root 0 8月 13 15:22 a.txt [root@localhost ~]# touch b.txt [root@localhost ~]# ll b.txt -rw-r--r--. 1 root root 0 8月 13 15:23 b.txt
-
_下划线:无特殊意义,可以用于名字的声明
-
=赋值,判断相等性
[root@localhost ~]# [ 1 = 1 ] # 条件1 = 1的左右两边必须有空格 [root@localhost ~]# echo $? # 判断上一条命令的结果是否为真,0=》true 0
-
|管道:把一个进程的处理结果传递给另外一个进程
[root@localhost ~]# ps aux | grep python xargs参数传递,把上一个命令的结果作为下一个命令的参数 [root@localhost ~]# find /home/ -type d -name "test*" |xargs ls 1.txt 2.txt 3.txt [root@localhost ~]# ls /home/test 1.txt 2.txt 3.txt
-
\转义特殊字符
[root@localhost ~]# mkdir a\ b.txt # 虽然可以,但不推荐 [root@localhost ~]# ll 总用量 0 drwxr-xr-x. 2 root root 6 8月 13 15:35 a b.txt [root@localhost ~]# echo $RMB # 默认会当成变量 [root@localhost ~]# echo '$RMB' # 取消特殊意义 $RMB [root@localhost ~]# echo \$RMB # 取消特殊意义 $RMB
-
[]条件测试,后续会详细介绍
[root@localhost ~]# name="egon" [root@localhost ~]# [ $name = "egon" ];echo $? 0 [root@localhost ~]# name="adf" [root@localhost ~]# [ $name = "egon" ];echo $? 1 [root@localhost ~]# [ -d /test ];echo $?
-
引号
'' 强引用(在单引号中都视为普通字符) " " 弱引用 (在双引号中保留变量) [root@localhost ~]# x=111 [root@localhost ~]# echo "$x" 111 [root@localhost ~]# echo '$x' $x
-
;与&&与||连接多条命令
[root@localhost home]# gagaga;ls # 不论前一条命令运行成功与否,都会执行后续命令 bash: gagaga: 未找到命令... egon [root@localhost home]# gagaga && ls # 只有前一条命令执行成功,才会执行后续命令 bash: gagaga: 未找到命令... [root@localhost home]# ls /test || mkdir /test # 前一条命令执行不成功才会执行后续命令 0.txt 1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt 9.txt
-
引号
'' 强引用(在单引号中都视为普通字符) " " 弱引用 (在双引号中保留变量) [root@localhost ~]# x=111 [root@localhost ~]# echo "$x" 111 [root@localhost ~]# echo '$x' $x
-
;与&&与||连接多条命令
[root@localhost home]# gagaga;ls # 不论前一条命令运行成功与否,都会执行后续命令 bash: gagaga: 未找到命令... egon [root@localhost home]# gagaga && ls # 只有前一条命令执行成功,才会执行后续命令 bash: gagaga: 未找到命令... [root@localhost home]# ls /test || mkdir /test # 前一条命令执行不成功才会执行后续命令 0.txt 1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt 9.txt
-
/路径分隔符
-
{}包含
[root@localhost home]# touch /test/{0..9}.txt # 当变量后面需要加上其他内容时将变量值加上{}例:echo ${x}RMB [root@localhost home]# ls /test/ 0.txt 1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt 9.txt
-
&后台运行
[root@localhost home]# echo "hello";sleep 3;echo "world" &
-
重定向
> >> 输出重定向 < << 输入重定向 > 覆盖 >> 追加 [root@localhost home]# cat >> a.txt << EOF > 111 > 222 > 333 > EOF 0标准输入、1标准正确输出、2标准错误输出,&标准正确和错误输出 [root@localhost home]# pwd 1>a.txt [root@localhost home]# cat a.txt /home [root@localhost home]# gagag 2>a.txt [root@localhost home]# cat a.txt bash: gagag: 未找到命令... [root@localhost home]# gagaga &>/dev/null < << 输入重定向 [root@localhost ~]# mysql -uroot -p123 < bbs.sql [root@localhost home]# grep root < /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin [root@localhost home]# dd if=/dev/zero of=/a.txt bs=1M count=10 记录了10+0 的读入 记录了10+0 的写出 10485760字节(10 MB)已复制,0.024387 秒,430 MB/秒 [root@localhost home]# dd </dev/zero >/b.txt bs=1M count=10 记录了10+0 的读入 记录了10+0 的写出 10485760字节(10 MB)已复制,0.0202365 秒,518 MB/秒 [root@localhost home]# ll /a.txt -rw-r--r--. 1 root root 10485760 8月 13 16:02 /a.txt [root@localhost home]# ll /b.txt -rw-r--r--. 1 root root 10485760 8月 13 16:03 /b.txt
-
?任意一个字符
[root@localhost ~]# ls ??.txt aa.txt [root@localhost ~]# ls a?c.txt a1c.txt [root@localhost ~]# rm -rf *txt
-
范围中的任意一个字符 [12] [ac] [a-z] [0-9]
[root@localhost ~]# touch a1c a2c axc aXc axd [root@localhost ~]# ls a?c a1c a2c axc aXc [root@localhost ~]# ls a[1x]c a1c axc [root@localhost ~]# ls a[a-z]c axc aXc [root@localhost ~]# ls a[A-Z]c # 不区分大小写 axc aXc [root@localhost ~]# ls a[x]c axc [root@localhost ~]# ls a[X]c aXc [root@localhost ~]# ls a[0-9]c a1c a2c [root@localhost ~]# ls /dev/sd[a-z]* /dev/sda /dev/sda1 /dev/sda2 /dev/sda3 /dev/sdb1
三:shell脚本使用补充
若脚本涉及到数据的读写操当,脚本中出现错误的脚本会对下面的运行数据产生很大的影响,这时我们可以添加相对应的命令应对。
#!/bin/bash # 脚本文件一行普遍有的标识
set -o errexit # 命令错误
set -o nounset # 变量错误
set -o pipefail # 管道错误
echo 1
exho 2
asijiojp # 错误命令
echo $y # 没有定义变量
echo 3
echo 5
asfaf | echo 123 # 管道错误
简单判断:
&&:并且
|| :或者
[root@localhost ~]# name="egon"
[root@localhost ~]# password="123"
[root@localhost ~]# [ $name = "egon" ] && [ $password = "123" ]
[root@localhost ~]# echo $?
0 # 正确
[root@localhost ~]# [ $name = "egon" ] && [ $password = "1263" ]
[root@localhost ~]# echo $?
1 # 错误
[root@localhost ~]# [ $name = "egon" ] || [ $password = "1263" ]
[root@localhost ~]# echo $?
0
四:shell脚本复合命令
4.1 流程控制 if 判断
1、什么是if判断
依据条件的真假来决定是否做事
2、为何要有if判断
为了让计算机能够像人一样去做判断
3、如何用
if 条件1;then
代码1
代码2
代码3
elif 条件2;then
代码1
代码2
代码3
elif 条件3;then
代码1
代码2
代码3
.......
else
代码1
代码2
代码3
fi
案例1
#!/bin/bash
echo "start......"
read -p "请输入您的年龄: " age
if [ $age -eq 18 ];then
echo "too young"
echo "too young"
echo "too young"
fi
echo "end......"
案例2
#!/bin/bash
echo "start......"
read -p "请输入您的年龄: " age
if [ $age -eq 18 ];then
echo "too young"
else
echo "too old"
fi
echo "end......"
案例3:
#!/bin/bash
read -p "请输入您的分数: " score
if [ $score -ge 90 ];then
echo "优秀"
elif [ $score -ge 80 ] && [ $score -lt 90 ];then
echo "良好"
elif [ $score -ge 70 ] && [ $score -lt 80 ];then
echo "一般"
else
echo "很差"
fi
案例4:
#!/bin/bash
read -p "请输入您的分数: " score
if [ $score -ge 90 ];then
echo "优秀"
elif [ $score -ge 80 ];then
echo "良好"
elif [ $score -ge 70 ];then
echo "一般"
else
echo "很差"
fi
案例5:
#!/bin/bash
read -p "输入用户名:" inp_user
read -p "输入密码:" inp_pwd
if [ $inp_user = "egon" ] && [ $inp_pwd = "123" ];then
echo "登录成功"
else
echo "用户名或者密码错误"
fi
二 流程控制之while循环
#!/bin/bash
while true
do
echo 111
echo 222
echo 333
done
案例1
#!/bin/bash
while true
do
read -p "输入用户名:" inp_user
read -p "输入密码:" inp_pwd
if [ $inp_user = "egon" ] && [ $inp_pwd = "123" ];then
echo "登录成功"
else
echo "用户名或者密码错误"
fi
done
案例2:
#!/bin/bash
while true
do
read -p "输入用户名:" inp_user
read -p "输入密码:" inp_pwd
if [ $inp_user = "egon" ] && [ $inp_pwd = "123" ];then
echo "登录成功"
break
else
echo "用户名或者密码错误"
fi
done
案例3:
# 多行
while 条件
do
命令1
命令2
命令3
done
# 一行
while 条件;do 命令1;命令2;命令3; done
while true;do ifconfig eth0;sleep 0.5;clear; done
三 流程控制之for循环
案例1
for i in {1..3}
do
echo ok1 $i
echo ok2 $i
echo ok3 $i
done
案例2
for x in "aaa" 2222 "ccc"
do
echo $x
done
案例3
#!/bin/bash
for i in {2..254}
do
(
ping -c1 1.1.1.$i &>/dev/null
if [ $? -eq 0 ];then
echo "1.1.1.$i ok"
else
echo "1.1.1.$i down"
fi
) &
done