20 shell编程基础
shell介绍
shell是一门解释型、弱类型、动态语言
变量
变量基础应用
#定义变量
[root@tencent_cloud ~]# name="egon"
[root@tencent_cloud ~]# age=18
[root@tencent_cloud ~]# height=1.8
#引用
[root@tencent_cloud ~]# echo $age
18
[root@tencent_cloud ~]# echo $height
1.8
#注意:这里和python不一样,等号连接的两侧不能有空格,除了整型和浮点型以外,与其他编程语言一样,建议字符串类型加上引号,规范书写。
#取值
[root@tencent_cloud ~]# money=100 #定义money=100
[root@tencent_cloud ~]# echo $money$ #后面加符号,不会影响
100$
[root@tencent_cloud ~]# echo $moneyRMB
#这样的话shell会误以为是$moneyRMB这个变量,所以要取值的话要用下面的方法
[root@tencent_cloud ~]# echo ${money}RMB
100RMB
#取消定义变量
[root@tencent_cloud ~]# unset name #取消定义变量### 引号对变量的影响
与用户交互
#交互式的变量
[root@tencent_cloud ~]# read -p "请输入您的账号:" name
请输入您的账号:egon
[root@tencent_cloud ~]# echo $name
egon
#指定-t时间参数,默认秒为单位
[root@tencent_cloud ~]# read -p "输入您的密码" -t 5 pwd
输入您的密码[root@tencent_cloud ~]# echo $pwd
[root@tencent_cloud ~]#
#- n 指定字符数
[root@tencent_cloud ~]# read -p "输入您的密码" -n 2 pwd
输入您的密码qw[root@tencent_cloud ~]#
格式化输出
[root@tencent_cloud ~]# user="egon"
[root@tencent_cloud ~]# age=18
[root@tencent_cloud ~]# echo "my name is $user my age is $age"
my name is egon my age is 18
#c语言风格的格式化输出
[root@tencent_cloud ~]# printf "my name is %s my age is %s\n" $user $age
my name is egon my age is 18
[root@tencent_cloud ~]# printf "my name is %s my salary is %.2f \n" "egon" 3.1415926
my name is egon my salary is 3.14 #指定输出小数,会四舍五入
骚操作输出
#\033[显示方式;前景色;背景色m
显示方式
0(默认值)、1(高亮)、22(非粗体)、4(下划线)、24(非下划线)、5(闪烁)、25(非闪烁)、7(反显)、27(非反显)
前景色
30(黑色)、31(红色)、32(绿色)、 33(黄色)、34(蓝色)、35(洋红)、36(青色)、37(白色)
背景色
40(黑色)、41(红色)、42(绿色)、 43(黄色)、44(蓝色)、45(洋红)
\033[0m 关闭所有属性
\033[1m 设置高亮度
\033[4m 下划线
\033[5m 闪烁
\033[7m 反显
\033[8m 消隐
\033[30m----\33[37m 设置前景色
\033[40m----\33[47m 设置背景色
#案例
echo -e "\033[1;34;40m 蓝色 \033[0m"
echo -e "\033[1;35;40m 洋红 \033[0m"
echo -e "\033[1;33;40m 黄色 \033[0m"
echo -e "\033[5;33;42m 你好骚啊! \033[0m"
预定变量
$* #获取所有的位置参数
$@ #获取所有的位置参数
$# #获取所有的位置参数个数
$$ #获取当前shell进程的pid
$? #获取上一条命令的运行状态,0代表成功 非0代表失败
$HOSTNAME #查看主机名
$HISTSIZE #查看最大历史记录条数
$PATH #查看环境变量
引号对变量的影响
"":软引用,有特殊意义
'':硬引用,引号里面的内容没有特殊意义
[root@tencent_cloud ~]# name="egon"
[root@tencent_cloud ~]# echo "hello $name"
hello egon
[root@tencent_cloud ~]# echo 'hello $name'
hello $name
``优先运行里面的内容
类似于$()
[root@tencent_cloud ~]# echo `date +%F`
2021-04-09
[root@tencent_cloud ~]# echo $(date +%F)
2021-04-09
作用域
[root@tencent_cloud ~]# x=111
[root@tencent_cloud ~]# bash
[root@tencent_cloud ~]# echo $x
[root@tencent_cloud ~]#
#这里涉及到了名称空间和作用域,由于你又开启了一个bash子进程,子进程里没有定义过x=111,所以这一echo不出来。
[root@tencent_cloud ~]# exit
[root@tencent_cloud ~]# export x
[root@tencent_cloud ~]# bash
[root@tencent_cloud ~]# echo $x
111
#继上面的操作,在最初声明export x,变量x都会作用于后续的bash子进程,但是由于linux可以多终端登录,不会影响到其他的终端。
环境变量
export x=111
#想要永久生效写到环境变量里
vim /etc/profile.d/HJBL.sh
#小细节:这里写环境变量的时候,尽量将环境变量给写到/etc/profile.d/*.sh中,从而降低出错风险,万一你自己手抖更改了/etc/profile里面的文件,你整个环境变量可能就崩了。
#在profile里面有这一行文件
for i in /etc/profile.d/*.sh /etc/profile.d/sh.local ; do
if [ -r "$i" ]; then
if [ "${-#*i}" != "$-" ]; then
. "$i"
else
. "$i" >/dev/null
fi
fi
done
#它在登录启动的时候会自动运行在/etc/profile.d/下所有*.sh的文件,所以写这里会安全的很多。
元字符
-
~家目录
-
.与..
-
!取反
[root@tencent_cloud test]# touch {1..9}.txt [root@tencent_cloud test]# touch {a..e}.txt [root@tencent_cloud test]# ls 1.txt 3.txt 5.txt 7.txt 9.txt b.txt d.txt 2.txt 4.txt 6.txt 8.txt a.txt c.txt e.txt [root@tencent_cloud test]# ls [1-9].txt 1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt 9.txt [root@tencent_cloud test]# ls [!1-9].txt a.txt b.txt c.txt d.txt e.txt
-
@无特殊意义
-
#注释
-
$取变量值
-
% + - * /
#整型运算用expr [root@tencent_cloud test]# expr 1 + 1 2 [root@tencent_cloud test]# expr 1 - 1 0 [root@tencent_cloud test]# expr 1 \* 8 8 [root@tencent_cloud test]# expr 8 / 2 4 [root@tencent_cloud test]# expr 8 % 3 #取余数 2 #浮点型运算要结合bc [root@tencent_cloud test]# res=`echo 10 / 3 | bc` [root@tencent_cloud test]# echo $res 3 [root@tencent_cloud test]# res=`echo "scale=2; 10 / 3" | bc` #指定小数位数 [root@tencent_cloud test]# echo $res 3.33
-
^同!一样
-
*任意多个字符
rm -rf /*
-
()在子shell中运行
-
_下划线:没有特殊意义,可以用于名字的声明
-
=赋值符号,在python中提倡两边有空格,shell里一定不能有空格
-
|管道:把一个进程的结果传递给另一个
-
\转义特殊字符,像上面的*运算
-
[]条件测试
运算符 作用 -d 测试文件是否为目录类型 -e 测试文件是否存在 -f 判断是否为一般文件 -r 测试当前用户是否有权读取 -w 测试当前用户是否有权写入 -x 测试当前用户是否有权执行 #判断是否存在这样的目录 [root@tencent_cloud ~]# [ -d /etc/fstab ] [root@tencent_cloud ~]# echo $? 1 #判断是否存在这样的文件 [root@tencent_cloud ~]# [ -f /etc/fstab ] [root@tencent_cloud ~]# echo $? 0
-
;与&&与||连接多个命令
#; 无论是否成功,都会运行后面的命令 [root@tencent_cloud test]# hahaha;ls -bash: hahaha: command not found 1.txt 3.txt 5.txt 7.txt 9.txt b.txt d.txt 2.txt 4.txt 6.txt 8.txt a.txt c.txt e.txt #&& 只有前面的成功,才会运行后面的 [root@tencent_cloud test]# hahaha && ls -bash: hahaha: command not found #|| 前面的运行不成功才会去运行后面的命令 [root@tencent_cloud test]# hahaha || ls -bash: hahaha: command not found 1.txt 3.txt 5.txt 7.txt 9.txt b.txt d.txt 2.txt 4.txt 6.txt 8.txt a.txt c.txt e.txt [root@tencent_cloud test]# cat 1.txt || ls #运行成功,后面没有执行 [root@tencent_cloud test]#
-
/路径分隔符
-
{}包含
#创建文件时 [root@tencent_cloud test]# touch {1..9}.txt [root@tencent_cloud test]# touch {a..e}.txt [root@tencent_cloud test]# ls 1.txt 3.txt 5.txt 7.txt 9.txt b.txt d.txt 2.txt 4.txt 6.txt 8.txt a.txt c.txt e.txt #取变量值 [root@tencent_cloud ~]# money=100 #定义money=100 [root@tencent_cloud ~]# echo $money$ #后面加符号,不会影响 100$ [root@tencent_cloud ~]# echo $moneyRMB #这样的话shell会误以为是$moneyRMB这个变量,所以要取值的话要用下面的方法 [root@tencent_cloud ~]# echo ${money}RMB 100RMB
-
重定向
>覆盖 >>追加 < <<输入重定向 [root@tencent_cloud test]# cat 1.txt [root@tencent_cloud test]# cat >1.txt<<EOF > hahaha > ni chi shi ba > EOF [root@tencent_cloud test]# cat 1.txt hahaha ni chi shi ba
-
?匹配任意一个字符
[root@tencent_cloud test]# touch a{1..3}c.txt [root@tencent_cloud test]# touch a{1..3}d.txt [root@tencent_cloud test]# ls a1c.txt a1d.txt a2c.txt a2d.txt a3c.txt a3d.txt [root@tencent_cloud test]# ls a?c.txt a1c.txt a2c.txt a3c.txt [root@tencent_cloud test]# ls a*.txt a1c.txt a1d.txt a2c.txt a2d.txt a3c.txt a3d.tx