Shell编程
Shell是一个命令行解释器,它为用户提供了一个向 Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shl来启动、挂起、停止甚至是编写一些程序。
Shell还是一个功能相当强大的编程语言,易编写,易调试,灵活性较强。Shel是解释执行的脚本语言,在Shel中可以直接调用 Linux系统命令。
echo 【选项】 【输出内容】
选项 -e 加上-e表示支持反斜线控制的字符转换
vi hello.sh
\#!/bin/Bash 表示写的脚本是shell脚本--主要是声明作用在这里#不是注释
\#leikaibi 这里的#表示注释功能
echo -e “这里写需要打印的内容”
保存退出
1. 赋予执行权限,chmod 755 hello.sh 命令 赋予脚本hello.sh脚本执行权限。然后通过路径/hello.sh来执行
2. 第二种方式。通过 bash hello.sh 来执行。
注意:如果运行在Windows下编写的脚本,会提示文件格式错误,这个时候我们就需要对文本中出现的特殊字符进行格式转换,直接在Linux命令行运行
dos2unix 【文件名】 这个时候就可以对该文件进行格式转换(如果这个命令没有安装,使用yum -y install dos2unix 进行安装就可以)
history 可以查询所有的历史命令
history 【选项】【历史命令保存文件】
vi .bash_history 可以查看所有的历史命令保存文件
按一下tab 键进行代码的补全 按两下tab键 可以对所有需要补全的代码进行罗列展示
alias 别名 ='原命令' # 设置命令别名
alias vi =‘vim’
这种别名只会临时生效,如果想要别名永久生效 需要更改配置文件
**快捷键**
Ctrl + C 强制终止当前的命令
Ctrl + L 清屏,相当于clear命令
Ctrl + U 删除或者剪切光标之前的命令。如果是输入了一个很长的命令不需要使用退格键一个一个的删除,使用这个快捷键更加的方便。
Ctrl + K 删除或者剪切光标之后的内容
Ctrl + Y 粘贴Ctrl + U 或者Ctrl + K 剪切的内容
Ctrl + D 退出当前终端
输出重定向
就是把原本应该输出到屏幕上内容输出到文件保存在文件中
动作 | 命令 | 说明 |
---|---|---|
标准输出重定向 | 命令 > 文件名 | 以覆盖的方式,把命令的正确输出,输出到制定的文件或者是设备中 |
标准输出重定向 | 命令 >> 文件名 | 以追加的方式,把命令的正确输出,输出到指定的文件或者是设备中 |
标准错误输出重定向 | 错误命令 2> 文件名 | 以覆盖的方式,把命令的错误输出,输出到指定的文件或者是设备中。 |
标准错误输出重定向 | 错误命令 2>>文件名 | 以追加的方式,把命令的错误输出,输出到指定的文件或者是设备中。 |
例如:执行 ls命令,我们就可以对ls命令输出的内容进行保存。ls >abc 就代表把ls要输出的内容保存到文件abc中,如果是 ls>> abc 就会把输出的内容追加到文件abc中。
注意:如果命令格式错误,就需要在>前加上2 例如 lst 2> abc
但是在实际的使用过程中,我们不会提前知道命令格式是正确的还是错误的,所以以上两种命令的用处不大。
===通常使用的是以下命令,把正确命令和错误命令都可以同时的保存:
动作 | 命令 | 说明 |
---|---|---|
正确输出和错误输出同时保存 | 命令 > 文件名 | 以覆盖的方式,把命令的正确输出,输出到制定的文件或者是设备中 |
正确输出和错误输出同时保存 | 命令 >> 文件名 | 以追加的方式,把命令的正确输出,输出到指定的文件或者是设备中 |
**输入重定向**
本来的输入是通过键盘直接输入的,现在我们通过文件的方式来输入,这就是输入重定向。
命令格式:
wc 【选项】【文件名】
选项: -c 统计字节数
-w 统计单词数
-l 统计行数
命令;命令 多个命令顺序执行,命令之间没有逻辑联系
命令1 && 命令2 逻辑与 命令1执行完之后,命令2才会继续往下执行
管道符
命令1 | 命令2 命令1的正确输出作为命令2的操作对象
? 匹配一个任意字符
\* 匹配0个或者多个任意字符,也就是 可以匹配任何内容
[ ] 匹配中括号中任意一个字符,例如:[abc] 代表一定匹配一个字符,或者是a,或者是b,或者是c。
[ - ] 匹配 括号中任意一个字符,- 代表一个范围,例如 [a-z] 代表匹配一个小写的字母
**Bash中的其他特殊符号**
‘ ’ 单引号,在单引号中的所有的特殊符号 如 “$” “\” 都是没有特殊含义的
“ ” 双引号 在双引号中特殊符号都是没有特殊含义。但是”$” “\” 是例外的。拥有调用变量的值。
例如给变量赋值 name = sc
‘ ’ 反引号的作用,反引号括起来的是系统命令。在bash中会优先的执行它。它的作用和$() 作用是一样的,不过推荐使用的是$() ,因为反引号在使用的过程中容易看错。
\# 在bash中 #开头的代表注释
$ 在调用变量的值,如果需要调用变量的的值的时候,需要使用$加变量名 的方式来获取到变量的值。
在bash中,变量的默认类型都是字符串类型的,如果要进行数值运算,就需要指定变量 类型为数值型。
**注意:**
变量是用等号连接,而且等号左右两端不能有空格
比如定义一个变量名为name的变量 name =” hello bianliang”,调用的时候,我们可以使用echo来调用
echo $name
![](https://i.imgur.com/VcpmtBC.jpg)
name="hello bianliang"
echo $name
输出结果:hello bianliang
调用的时候只需要记住,在变量名之前加$符号
变量查看 set
变量删除 unset name
主要保存的是和系统操作环境相关的数据。
用户自定义变量只在当前的shell中生效,而环境变量会在当前shell和这个shell的所有子shell中生效,如果把环境变量写入相应的 配置文件中那么这个环境变量就会在所有的shell中生效。
设置环境变量
Export 变量名=变量值 #申明变量
例如我们定义两个变量
name=lei
export sex =nan
我们通过set命令查看变量就会查看到两个已经定义好的变量,但是这个时候如果我们再进入一个bash(通过命令bash 进入, 我们可以通过pstree来查看进程数)
env # 专门的用来查看变量的命令
Unset 变量名 # 删除环境变量
这种变量只要是用来向脚本当中传递参数或者是数据的,变量名不能自己定义,变量的作用是固定的,只能更改里面的值
位置参数变量 | 作用 |
---|---|
$n | n在这里代表的是数字,$0 代表命令本身,$1– 9 代 表 的 是 第 一 到 第 九 个 参 数 , 十 个 以 上 的 参 数 需 要 用 大 括 号 例 如 9 代表的是第一到第九个参数,十个以上的参数需要用大括号 例如 9代表的是第一到第九个参数,十个以上的参数需要用大括号例如{10} |
$* | 这个命令代表命令行中所有的参数,$* 把所有的参数看成一个整体 |
$@ | 这个命令也代表的是命令行中所有的参数,不过不同的是$@ 把每个参数区别对待 |
$# | 这个命令代表命令行中所有参数的 个数 |
我们通过一个简单的例子来查看一个使用方法,我们写一个bash
Canshu.sh定义两个参数,然后输出两个参数的和
#!/bin/bash
sum1=$1
sum2=$2
sum=$(($sum1+$sum2))
echo "sum is : $sum"
然后使用命令echo 给这个sh 赋予执行权限
Chmod 755 canshu.sh
执行canshu.sh 并向这个sh传入两个参数 11 22 求和
[root@iZwz92dpr9gpgasbo4gg15Z sh]# ./canshu.sh 11 22
下面通过一个简单的sh来看一个几个位置参数的区别。
Canshu2.sh
\#!/bin/bash
echo $#
echo $*
echo $@
赋予执行权限 [root@iZwz92dpr9gpgasbo4gg15Z sh]# chmod 755 canshu2.sh
输出结果:
[root@iZwz92dpr9gpgasbo4gg15Z sh]# ./canshu2.sh 11 22 33 44 55 66
6
11 22 33 44 55 66
11 22 33 44 55 66
注意: ∗ 和 * 和 ∗和@的区别,具体的区别可以在for 循环中看出
$*中的所有参数看成是一个整体,所有在for循环中只会循环一次
@ 中 的 每 个 参 数 都 看 成 是 相 互 独 立 的 , 所 以 @ 中的每个参数都看成是相互独立的,所以 @中的每个参数都看成是相互独立的,所以@ 中有几个参数,就会循环几次
例如:
\#!/bin/bash
for x in "$*"
do
echo $x
done
for y in "$@"
do
echo $y
done
运行结果:
[root@iZwz92dpr9gpgasbo4gg15Z sh]# chmod 755 canshu3.sh
[root@iZwz92dpr9gpgasbo4gg15Z sh]# ./canshu3.sh 1 2 3 4 5
1 2 3 4 5
1
2
3
4
5
###4.预定义变量
预定义变量 | 作用 |
---|---|
$? | 最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令是正确的;如果这个变量的值是非0(具体是哪一个数,由命令自己决定),则证明上一个命令执行不正确了。 |
$$ | 当前进程的进程号 |
$! | 后台运行的最后一个进程的进程号(PID) |
例如使用echo $? 我们就可以打印出 来看看上一条命令是否正确执行
Echo $$ 查看当前进程号pid
接受键盘输入
Read【选项】【变量名】
选项:-p 提示信息—在等待read输入时,输出提示信息
-t 秒数 read命令会一直等待用户输入,使用此选项可以指定等待时间
-n 字符数: read命令只接受指定的字符数, 就会在执行
-s 隐藏输入的数据,适用于机密信息的输入
Declare 声明变量类型
declare 【+/-】【选项】【变量名】
- 给变量设定类型属性
+ 取消变量的类型属性
-i 将变量声明为整数型(integer)
-x 将变量声明为环境变量
-p 显示指定变量的被生命的类型
数值运算:
方法一:
aa=11
bb=22
declare -i cc= a a + aa+ aa+bb #将变量aa和bb 进行数值运算、
方法二:使用expr或者let数值运算工具
方法三:使用 $((运算式)) 或者是 [ 运 算 式 ] f f = [运算式] ff = [运算式]ff=(( a a + aa+ aa+bb))
推荐 使用方法三
主要的作用是通过判断x的值来判断y是否有值
##5. 环境变量配置文件
1.环境变量配置文件简介
Source命令
Source 配置文件或者 .配置文件
环境变量配置文件中主要是定义对系统的操作环境生效的系统默认环境变量,
比如PATH HISTZIZE PSI HOSTNAME等默认环境变量
2.环境变量配置文件作用
/etc/下的环境变量对所有的用户都是生效的
/etc/profile
/etc/profile.d/*.sh
正则表达式和通配符
正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配。grep、awk、sed等命令可以支持正则表达式。
通配符用来匹配符合条件的文件名,通配符是完全匹配。ls、find、cp这些命令不支持正则表达式,所以只能使用shell自己的通配符来进行匹配了。
通配符匹配的是文件名,正则表达式是指在一个文件中搜索符合要求的字符串
基础正则表达式
在搜索文件时, 我们可以通过grep命令来进行匹配
grep “aa*” 文件名 # 匹配至少包含一个a的行
grep “s..d” 文件名 # 会匹配在字母s和d之间一定有两个字符的单词
Cut字段提取命令
cut 【选项】 文件名
选项:
-f 列号 提取第几列
-d 分隔符 按照指定分隔符分割列
注意:一般cut命令不独立使用,都是跟管道符grep命令配合使用
命令 df -h 查看分区使用率
Printf命令
格式化打印命令,如果想要学习awk命令 需要先学习printf命令
输出类型
%ns :输出字符串 n是数字代表输出几个字符
%ni 输出整数,n是数字指输出几个字符
%m.nf 输出浮点数
在awk命令输出中支持print和printf命令
Print: print命令会在每个输出之后自动加入一个换行符(Linux默认是没有print命令的,只能在awk中使用)
Printf命令是标准格式输出命令,并不会自动增加换行符,如果需要换行,需要手动增加换行符。
Awk命令
命令格式
Awk ‘条件1{动作1} 条件2{动作2}...’ 文件名
条件:一般使用条件关系表达式作为条件
X>10 判断变量x是否大于10
X>=10 大于等于
X<=10 小于等于
动作:
格式化输出
流程控制语句、
例如:
使用awk 命令输出df -h磁盘信息的第一列和第五列第六列
awk '{print $1 "\t" $5 "\t" $6}'
[root@iZwz92dpr9gpgasbo4gg15Z ~]# df -h | awk '{print $1 "\t" $5 "\t" $6}'
Filesystem Use% Mounted
/dev/vda1 27% /
devtmpfs 0% /dev
tmpfs 0% /dev/shm
tmpfs 1% /run
tmpfs 0% /sys/fs/cgroup
tmpfs 1% /run/user/0
[root@iZwz92dpr9gpgasbo4gg15Z ~]#
**BEGIN 命令 **
[root@iZwz92dpr9gpgasbo4gg15Z ~]# awk 'BEGIN{print{"zhe shi yi ge begin "} {print $1}'
在所有的命令执行之前先执行begin命令
Sed命令
sed命令是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用,功能不同凡响。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出。sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。
Sed是几乎包括在所有的UNIX平台当然也包括Linux的轻量级流编辑器。Sed主要是用来将数据进行选取、替换、删除、新增的命令。
和vi的区别,vi只能用来修改文件中的内容。Sed不仅能修改文件而且还可以直接修改命令的结果。在shell脚本中sed是一个非常重要的编辑器
命令格式:
Sed 【选项】 ‘ 【动作】’ 文件名
选项:
-n :一般sed命令会把所有数据都输出到屏幕上,如果加上这个选项,则只会把sed命令处理过的行输出到屏幕上
-e :允许对输入数据应用多条sed命令编辑
-i :用sed修改结果直接修改读取数据的文件,而不是由屏幕直接输出
动作:
a\: 追加,在当前行后添加一行或者多行。添加多行时,除最后一行外,每行末尾都需要用\ 代表数据完结
Sed ‘2a zhuijia de neirong’ 文件名 这样我们就在文件中的第二行的后面追加了我们输出的内容
c\ : 行替换
i\: 行插入
Sed ‘2i charu’ 文件名 在第二行之前插入了一个内容为charu的内容
d\: 删除,删除指定的行
P: 打印,打印指定的行
h 拷贝模板块的内容到内存中的缓冲区。
H 追加模板块的内容到内存中的缓冲区。
g 获得内存缓冲区的内容,并替代当前模板块中的文本。
G 获得内存缓冲区的内容,并追加到当前模板块文本的后面。
l 列表不能打印字符的清单。
n 读取下一个输入行,用下一个命令处理新的行而不是用第一个命令。
N 追加下一个输入行到模板块后面并在二者间嵌入一个新行,改变当前行号码。
p 打印模板块的行。
P(大写) 打印模板块的第一行。
q 退出Sed。
排序命令
Sort 【选项】 文件名
选项
-f :忽略大小写
-n :以数值型进行排序,默认的是使用的字符串型进行排序
-r :反向排序
-t :指定分隔符,默认的分隔符是制表符
-k n[,m] : 按照指定的字段范围排序,从第n个字段开始,m字段结束,默认是到行尾。
统计命令wc
Wc 【选项】文件名
选项:
-l 只统计行数
-w 只统计单词数
-m 只统计字符数
按照文件类型进行判断
-b:判断文件是否存在,并且是否为块设备文件
-c:判断该文件是否存在,并且是否是字符设备文件
-d:判断该文件是否存在,并且是否是目录文件
-e:判断该文件是否存在
-f:判断该文件是否存在。并且是否是普通文件
判断格式: test -e /root/install.log 可以判断root目录下install.log文件是否存在
或者 [ -e /root/install.log] 也可以进行判断
两个文件之间进行比较
文件1 -nt 文件2 :判断文件1的修改时间是否比文件2的新
文件1 -ot 文件2: :判断文件1的修改时间是否比文件2的旧
文件1 -ef 文件2 : 判断文件1是否和文件2的inode号是否一致,可以理解为两个文件 是否是同一个文件。这个判断用于判断硬链接是很好的方法。
两个整数之间的比较
整数1 -eq 整数2 :判断整数1是否和整数2相等
整数1 -ne 整数2 :判断整数2是否和整数2不相等
整数1 -gt 整数2 :判断整数1是否大于整数2
整数1 -lt 整数2 :判断整数1是否小于整数2
整数1 -ge 整数2 :判断整数1是否大于等于整数2
整数1 -le 整数2 :判断整数1是否小于等于整数2
字符串的判断
-z 字符串 :判断字符串是否为空
-n 字符串 :判断字符串是否为非空
字符串1==字符串2 :判断字符串1是否和字符串2相等
字符串1!=字符串2:判断字符串1是否和字符串2不相等
多重条件判断
判断1 -a 判断2 :逻辑与,判断1和判断2都成立,最终的结果才为真
判断1 -o 判断2 :逻辑或,判断1和判断2有一个成立,最终的结果就为真
!判断 : 逻辑非,使原始的判断式取反
我们在进行判断的时候;
[-e /root] 判断root文件是否存在,如果存在我们可以通过命令行 echo $? 返回0 就说明存在,如果返回的是非0,就说明不存在。
或者[-e /root] &&echo yes || echo no
单分支if条件语句
If [条件判断式] ; then
程序
fi
或者
If [ 条件判断式]
then
程序
fi
注意:
是以if 开头 以fi 结尾
条件判断式中就是使用test命令判断,所以中括号和条件判断式之间必须有空格
then后面跟的是符合条件之后执行的程序,可以放在[] 之后,用;分割,也可以换行写入,就不需要了
双分支if条件语句
If [条件判断式]
then
条件成立时,执行的程序
else
条件不成立时,执行的另一个程序
Fi
多分支if条件语句
If [条件判断1]
then
条件成立时,执行的程序
elif
条件判断2成立时,执行程序2
else
当所有条件都不成立时,最后执行此程序
Fi
case只能判断一种条件关系,而if语句可以判断多种条件关系、
Case $变量名 in
“值1”)
“执行语句”
::
“值2”)
“执行语句”
...
Esac
语法格式:
For 变量 in 值1 值2 值3 ...
Do
程序
Done