Shell脚本保姆级教程,建议收藏
Posted 汤米先生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Shell脚本保姆级教程,建议收藏相关的知识,希望对你有一定的参考价值。
文章目录
前言
总结了一下Shell脚本的基础知识,都结合了示例,通俗易懂。一. Shell基础
shell是命令解释器的一个总称
计算机是由计算机硬件组成的,但是人类无法直接使用硬件,于是就产生了操作系统内核来控制计算机硬件,但是操作系统内核也不能被人们直接操作,例如我们所熟知的window系统和Linux系统,这些就是通过用户应用程序来控制系统内核的,众所周知计算机只能识别0和1,而命令解释器就是用来将人类自然语言转化为计算机能识别语言(0和1)的媒介,当然,不同的命令也有不同的解释器,常见的解释器有:
- /bin/bash (常用的)
- /bin/sh
- /bin/csh
- /bin/tcsh
解释器负责将用户的指令翻译为内核可以识别的指令。
通过usermod,chsh可以更改登录Shell。
下面说一下关于解释器的一些操作
1. 查看
我们可以 输入 cat /etc/shells
来查看我们拥有那些解释器
2. 安装
我们可以通过输入 yum -y install xxx
来安装我们想要的解释器、
3. 使用
我们可以通过输入 usermod -s 解释器名字 用户名
来使用这个解释器
然后输入 grep 用户名 /etc/passwd
来查看当前正在使用的解释器
也可以使用 chsh -s 解释器名字 用户名
将解释器修改回来
4. Bash基本特性
Bash的作为默认的解释器自然有他的道理,下面就来解释一下,Bash解释器的一些特别之处。
Bash解释器具有许多方便的快捷键
- Ctrl + a :移到命令行首
- Ctrl + e :移到命令行尾
- Ctrl + r:逆向搜索命令历史
- Ctrl + l:清屏
- Ctrl + o:执行当前命令,并选择上一条命令
- Ctrl + s:阻止屏幕输出
- Ctrl + q:允许屏幕输出
- Ctrl + c:终止命令,将我们当前执行的命令撤销掉
- Ctrl + z:挂起命令
- Ctrl + g:从历史搜索模式退出
- Ctrl + f :按字符前移(右向)
- Ctrl + b :按字符后移(左向)
- Alt + f :按单词前移(右向)
- Alt + b :按单词后移(左向)
- Ctrl + xx:在命令行首和光标之间移动
- Ctrl + u :从光标处删除至命令行首
- Ctrl + k :从光标处删除至命令行尾
- Ctrl + w :从光标处删除至字首
- Alt + d :从光标处删除至字尾
- Ctrl + d :删除光标处的字符
- Ctrl + h :删除光标前的字符
- Ctrl + y :粘贴至光标后
- Alt + c :从光标处更改为首字母大写的单词
- Alt + u :从光标处更改为全部大写的单词
- Alt + l :从光标处更改为全部小写的单词
- Ctrl + t :交换光标处和之前的字符
- Alt + t :交换光标处和之前的单词
- Alt + Backspace:与 Ctrl + w 相同类似
- 还有 Tab 快速补全代码快捷键,可以大大的减少我们的代码编辑量
查看历史命令
可用通过上下键来查看使用过的命令记录,对于一些的重复的命令我们就不必再去敲一遍了。
命令别名
有些命令具有别名 比如 ll = ls -l
也就是给一个命令又起了个名字,简写了,我们也可以自己创建别名,来提高编辑代码的速率。
标准输入输出的重定向
把输出不显示到屏幕上而显示到文件中
使用 `>` 将输出显示在文件中,同时 `>` 也意味着**覆盖**文件中以前的内容,使用 `>>` 才是在原内容上**追加**的意思
并不是所以的输出信息都可以用 >或者>>添加到文件中,以上正常的输出可以,但是错误的输出 就不行了
我们可以用 2>
来将错误的输出添加到文件中
但如果又有错误又有正常输出信息呢?我们该如何把他们存放到文件中?
我们可以使用 &>
将他们一块儿存入文件中,同样的一个 > 都是覆盖,>> 是追加
管道
管道可以联合多条命令,将第一条命令的结果给第二条命令使用
比如我们来实行一下 过滤操作 ,从yum 列表中筛选出含有 bash 的软件
yum list | grep bash
二. hello world
我们还是先从创建第一个 hello world 开始
首先创建一个脚本:文件
shell/day1 是我提前创建好的目录
vim /root/shell/day1/first.sh
按s 插入Shell命令
echo "hello world -tom"
按Esc 输入 :x
保存并退出
然后给脚本添加可执行权限
chmod +x /root/shell/day1/first.sh
下一步 就可以执行这个脚本了
vim /root/shell/day1/first.sh
在上面步骤中有关键的一步 ,就是给脚本文件可执行权限 ,其实有一种方法,可以不用给权限还能运行脚本
在不具有可执行权限时,我们可以用下面方法执行脚本
- 解释器 脚本文件名 例如 :bash first.sh
- source 脚本文件名 这种方法不会启动子进程,我们可以通过 pstree(需要下载)查看进程树来观察不同。
三. 变量
1. 自定义变量
定义变量
变量名=变量值
取消变量
unset 变量名
变量规范
- 变量 = 两边不能加空格,不能使用关键字做变量名,如ls,cd等等。
- 如果变量名已经存在则覆盖以前的变量名 。
- 变量名称只能由字母数字下划线组成,而且不能以数字开头。
- 在打印一个变量的时候,最好用
{}
括起来
2. 环境变量
变量名为大写,由操作系统维护 ,这些都是系统提前设置好的变量
- 存储在/etc/profile或~/.bash_profile中
- 命令env可以列出所有的环境变量
- 常见的环境变量有:PATH,PWD,USER,UID,HOME,SHELL
PATH:命令搜索变量,负责搜索命令是否存在
PWD:显示当前所在路径的变量
USER:显示当前用户名
UID:显示当前用户的ID号
HOME:当前用户的家目录
SHELL:显示当前正在使用的解释器
3. 位置变量
bash内置变量 ,存储脚本执行时的参数
使用$n表示,n为数字序列号,如果n<10用 $n表示 ,如果n>10,用 ${n}表示
下面就来演示一下位置变量的使用方法:
先创建一个脚本文件
vim /root/shell/day1/a.sh
然后在脚本文件中设置 三个位置变量
echo $1
echo $2
echo $3
然后再给文件 可执行 权限
chmod +x /root/shell/day1/a.sh
最后 给位置变量赋值,再执行脚本文件
/root/shell/day1/a.sh aa bb cc
第一个位置变量 aa
, 第二个位置变量 bb
,第三个位置变量cc
。
4. 预定义变量
bash内置变量,可以调用,但不能赋值和修改,用来保存脚本程序的执行信息。
变量名 | 含义 |
---|---|
$0 | 当前所在的进程或脚本名 |
$$ | 当前运行进程的PID号 |
$? | 命令执行后的返回状态,0表示正常,1或其他值表示异常,只针对上一条命令 |
$# | 以加载的位置变量的个数 |
$* | 所有位置变量的值 |
下面是$?
用法和其余几个的用法
错误显示非0,正常显示0
后面aa bb cc dd是4个位置变量的值
5. 单引号和双引号的区别
下面来举个例子
可以看出 ""
可以识别特殊符号 而 ' '
不能识别特殊符号
其中还有 `` 反引号 与 $() 等效 ,引号和括号内都是命令, 整体得到的是命令执行的结果(a= $(),a得到的是括号内命令执行的结果)
6. 变量使用实例
read的使用
将输入的值赋给后面的变量
例如
read -p "请输入用户名:" username
会把提示后的输入的值赋给变量 username
但如果不给提示加双引号,会出现下面情况
如果我们设置输入密码
read -s -p "请输入密码:" password
前面加上-s 在我们输入时就不显示输入的内容了 安全性高点
read 还有一个 -t
方法 ,限定在多少秒内输入 ,否者就退出输入
read -t 3 -p "请输入用户名:" username
限定用户三秒内 输入
局部变量和全局变量
局部变量 : 新定义的变量默认只在当前的Shell环境中生效,无法在子Shell环境中使用
全局变量 :全局变量在当前Shell和子Shell环境中均有效
设置一个局部变量
a=11
在当前的Shell中有效,但在bash中无效
下面我们设置一个全局变量
export b=22
可以看出在当前Shell中有效,在bash中也有效
四. Shell中基本运算
1. 整数运算
Shell 中有 + - * / %(取余)
下面演示一下
主要的执行方式 有两种
- $(())
- $[]
同时也支持一些简写表达式
简写表达式 | 完整表达式 |
---|---|
i++ | i=i+1 |
i- - | i=i-1 |
i+=2 | i=i+2 |
i-=2 | i=i-2 |
i*=2 | i=i*2 |
i/=2 | i=i/2 |
i%=2 | i=i%2 |
2. 小数运算
Bash内建机制仅支持整数运算,不支持小数运算,我们可以通过计算机软件bc实现小数运算
bc支持交互式和非交换式两种方式计算,scale=n可以约束小数位
交互执行
非交互执行
bc也同样支持比较操作符
表达式成立返回1,不成立返回0
五. 条件测试
1. test测试操作
语法格式
test 选项 参数
[ 选项 参数 ]
基本语法:
是否为空[ -z 字符串 ]
等于 [ 字符串1 == 字符串2 ]
不等于[ 字符串1!= 字符串2 ]
显示 0 为正确
显示 非0 为不成立
2. 整数值比较
格式:[整数值1 操作符 整数值2]
操作符 | 含义 |
---|---|
-eq | 等于 |
-ne | 不等于 |
-ge | 大于或等于 |
-le | 小于或等于 |
-gt | 大于 |
-lt | 小于 |
应用
2 大于 1 ,输出 0符合
2 不大于 3, 输出 1(非0)不符合
3. 文件状态测试
操作符 | 含义 |
---|---|
-e | 判断对象是否存在,若存在则结果为真 |
-d | 判断对象是否为目录 |
-f | 判断对象是否为一般文件 |
-r | 判断对象是否有可读权限 |
-w | 判断对象是否有可写权限 |
-x | 判断对象是否有可执行权限 |
应用
/etc/ 为存在对象
/eeee/ 不纯在
4. 组合命令
我们可以使用控制符将多个命令组合
格式 : 命令1 控制符 命令2
控制符有:
;
: 前后两个命令没有逻辑关系,先执行前面的命令,然后再执行后面的命令,无论前面的命令是否执行成功 ,都会执行后面的命令。&&
: 先执行前面的命令,然后再执行后面的命令,唯有前面的命令成功,才会执行后面的命令。||
:先执行前面的命令,然后再执行后面的命令,当前面的命令执行成功时,便不在执行后面的命令,只有前面的命令执行不成功,才会执行后面的命令
应用
先进入 /root/shell 目录,再查看目录内容,会显示day1
打印 day1 表示 两条命令执行成功
我们也可利用 && 和 || 来实现多个条件的判断
[判断1] || [判断2]
[判断1] && [判断2]
5. 监控脚本基础知识
tr -s :删除多余重复的字符
例如 将 “a b c”中多余重复的空格去掉
echo "a b c" | tr -s " "
最终字母之间都只留下了一个空格
cut过滤
格式 : cut -d分割符号 -第几列 目标文件
类如 我们以 /etc/passwd 为目标文件,以 :
为分隔符号 ,获取第一列内容
cut -d: -f1 /etc/passwd
六. if语句
1. 单分支if语句
格式1:
if 条件
then 命令
fi
格式2:
if 条件 ;then
命令
fi
两种格式都可以使用 ,如果条件成立,执行命令,否者什么也不做。
下面来写一个创建用户脚本
条件为用户名和密码都不能为空,命令是创建用户并修改密码,最后的 echo 打印空 ,也就是换行。
由于 read pass 带了 -s 所以输入的密码不显示,实际是输入了密码。
read -p "请输入用户名:" user
read -s -p "请输入密码:" pass
if [ ! -z "$user" ]&&[ ! -z "$pass" ];then
useradd "$user"
echo "$pass" | passwd --stdin "$user"
fi
echo
2. 双分支if语句
格式1:
if 条件
then 命令1
else
命令2
fi
格式2:
if 条件;then
命令1
else
命令2
fi
格式3:
if 条件1;then
命令1
elif 条件2; then
命令2
......
else
命令n+1
fi
下面写一个例子:
测试主机是否能ping通
#!/bin/bash
if [ -z "$1" ];then
echo -n "用法:脚本"
echo -e "\\033[32m域名或IP\\033[0m"
exit
fi
ping -c2 -i0.1 -W1 "$1" &>/dev/null
if [ $? -eq 0 ];then
echo "$1 is up"
else
echo "$1 is down"
fi
echo
-c2
:ping两次结束
-i0.1
:ping的间隔是0.1秒
-W1
:ping的反应时间为1秒,若ping的反应时间超过1秒,默认ip ping不通
当我们什么都不输入时,会提示格式,当我们随便输入一个ip,显示ip 关闭 ,当我们输入自己的ip时显示 ip 开启
七. for 循环
根据变量的不同取值,重复执行命令序列
格式1:
for 变量 in 值列表
do
命令
done
格式2:
for ((初值;条件;步长))
do
命令
done
下面举个例子(格式1)
#!/bin/bash
for i in 1 23 abc 2g
do
echo "I am $i"
done
可以看出循环执行了5次,将in后内容遍历了一遍
格式1中的值列表有多种表示方式,也可以这样写
for i in {1..10}
for i in {a..z}
for i in {A..Z}
表示1到10,a到z,A到Z
下面再举个例子(格式2)
#!/bin/bash
for((i=1;i<=5;i++))
do
echo "I am $i"
done
这个就不必多说了。
99乘法表
下面来运用for循环的格式2来写一个99乘法表
#!/bin/bash
for((i=i;i<=9;i++))
do
for((j=1;j<=i;j++))
do
echo -n "$i*$j=$[i*j]"
done
echo
done
八. while循环
条件式循环,反复测试条件,只要成立就执行命令序列。
格式:
while 条件
do
命令
done
举个例子
遍历输出1-5
#!bin/bash
i=1
while [$i -le 5 ]
do
echo $i
let i++
done
猜数字游戏
给出一个10以内的随机数让玩家猜,如果输入的数大于随机数,会显示猜大了,如果输入的数小于随机数,则显示猜小了。
#!/bin/bash
num=$[RANDOM%10+1]
while:
do
read -p "请输入1-10之间的整数:" guess
if [$guess -eq $num ];then
echo "恭喜你,猜对了"
exit
elif [ $guess -lt $num ];then
echo "猜小了"
else
echo "猜大了"
fi
done
九. case语句
效果类似于多分支的if语句,如果与预设的值相匹配,则执行相应的操作,命令最后以 ;
结尾,如果都不匹配,则执行默认命令。
格式:
case 变量 in
模式1)
命令1;;
模式2)
命令2;;
......
*)
默认命令
esac
举一个例子
输入 tom 输出 I am tom ,输入tome 输出 I am tome ,输入其他的 则 输出 暂无此人。
#!/bin/bash
read -p "请输入tom 或者 tome:" key
case $key in
tom)
echo "I am tom";;
tome)
echo "I am tome";;
*)
echo "暂无此人"
esac
石头剪刀布游戏
运用数组和case语句来创造一个石头剪刀布游戏脚本,系统会随机选择出拳的方式。
#!/bin/bash
gane=(石头 剪刀 布)
num=$[RANDOM%3]
computer=${game[$num]}
#通过随机数获取系统的出拳
#出拳的可能保存在一个数组中:game[0],game[1],game[2]
echo "请根据下列提示选择您的出拳方式"
echo "1.石头"
echo "2.剪刀"
echo "3.布"
read -p "请选择1-3:" person
case $person in
1)
if [ $num -eq 0];then
echo "平局"
elif [ $num -eq 1 ];then
echo "你赢"
else
echo "电脑赢"
fi;;
2)
if [ $num -eq 0 ];then
echo "电脑赢"
elif [ $num -eq 1 ];then
echo "平局"
else
echo "你赢"
fi;;
3)
if [ $num -eq 0 ];then
echo "你赢"
elif [ $num -eq 1 ];then
echo "电脑赢"
else
echo "平局"
fi;;
*)
echo "必须输入1-3的数字"
esac
数组
数组是一个特殊的变量,它是能够储存多个数据的集合
格式:
数组名=(数值1 数值2 数值3 ...)
下面来演示一下
创建一个名为 test 的数组
十. shell函数
在Shell环境中,将一些需要重复使用的操作,定义为公共的语句块,既可称为函数
格式1:
function 函数名{
命令
...
}
格式2:
函数名(){
命令
...
}
范例
不带参数的函数
imsg(){
echo "hello world"
echo "compute cloud"
}
带参数的函数
add(){
echo $[$1+$2]
}
带颜色的函数
\\033[
:开启设置字体颜色
\\033[0m
: 关闭设置字体颜色
#!/bin/bash
cecho(){
echo -e " \\033[$1m$2\\033[0m"
}
cecho 31 OK #参数是字体的颜色
cecho 32 OK
cecho 33 OK
cecho 34 OK
十一. 中断和退出
脚本中的中断和退出命令
continue
: 可以结束单次循环
break
:可以结束循环体
exit
:可以退出脚本
下面举几个例子
首先是continue ,当遍历到 3 时,跳过本次循环
然后是 break
当遍历到 3 时跳出循环
最后是 exit
如果是在脚本文件中,会退出脚本,如果在xshell中直接exit,则会退出连接。
十二. 字符串的处理和变量的初始化
统计变量长度
test=123456789
echo ${#test}
1. 字符串的截取
格式:${变量:起始位置:长度}
text=123456789
从第0位开始往后截取3位
echo ${test:0:3}
从第3位开始,往后截取3位
echo ${test:3:3}
从第四位开始,截取到最后一位
echo ${test:4}
从第四位开始,截取到倒数第二位
echo ${test:4:-2}
2. 字符串的替换
替换一个结果
格式:${变量/旧字符/新字符}
替换全部结果
格式:${变量//旧字符/新字符}
示例
3. 字符串的掐头去尾
掐头
字符串的掐头都是从左到右,且不会改变变量原来的值
最短匹配
格式 : ${变量#关键词}
最长匹配
格式:${变量##关键词}
举例
定义变量 test=123:456:789
分别最短匹配掐头和最长匹配掐头
*:
表示 :
前面的所有部分
去尾
去尾的顺序是从右往左,同样不会改变变量原来的值
最短匹配
格式: ${变量%关键词}
最长匹配
格式:${变量%%关键词}
举例
与上面的例子差不多
因为顺序改变了,所以 * 的位置也变了一下
4. 变量初始化
判断一个变量是否有值,如果有值返回该变量的值,如果没有值,则返回初始值
格式:${变量:-初始值}
示例
此处给a变量赋值,b没有赋值,使用变量格式化,a返回原有的值,b返回变量初始化的值。
5. 随机密码
定义变量:10个数字+52个字母,用随机数对62取余数,返回的结果为[0-61],然后将其作为key的字符串位数取出字符,随机取10次,得到一个10位的随机密码。
#!/bin/bash
key="1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
pass=""
for i in {1..10}
do
num=$[RANDOM%${#key}]
tmp=${key:num:1}
pass=${pass}${tmp}
done
echo $pass
使用命令生成随机密码
- uuidgen:生成随机序列号
- openssl: 生成可控长度的随机序列号,例子后面的15不是指的序列号的长度,而是一个控制值,值越大,序列号越长。
使用随机设备文件生成随机密码
/dev/random
: 能够一直产生随机码,不会自动终止,效率很慢,大概十几秒出一次。
/dev/urandom
: 这个文件也能源源不断的产生随机码,而且效率很高。
十三. 正则表达式
描述一个字符集合的表达方式,根据特征模糊的匹配内容。
1. 基本正则符号
正则符号 | 描述 |
---|---|
abc | 匹配abc |
^ | 匹配开头 |
$ | 匹配结尾 |
[集合] | 匹配集合中的任意单个字符 |
[ ^ 集合] | 对集合取反 |
. | 匹配任意单个字符 |
* | 匹配前一个字符任意次(包含0次) |
. * | 匹配任意 |
{n,m} | 匹配前一个字符n到m次 |
{n,} | 匹配前一个字符至少n次 |
{n} | 匹配前一个字符n次 |
2. 扩展正则符号
正则符号 | 描述 |
---|---|
+ | 匹配前面的字符至少一次 |
? | 匹配前面的字符0或一次 |
() | 组合与保留 |
| | 或者 |
{n,m} | 匹配前面的字符n到m次 |
{n,} | 匹配前面的字符至少n次 |
{n} | 匹配前面的字符n次 |
3. Perl兼容的正则符号
正则符号 | 描述 |
---|---|
\\b | 匹配单词边界 |
\\w | 匹配字符数字下划线 |
\\W | 和\\w相反 |
\\s | 匹配空白 |
\\d | 匹配数字 |
\\d+ | 匹配多个数字 |
\\D | 匹配非数字 |
4. grep语法
grep语法支持正则表达式,下面介绍一下grep语法,以及一些正则表达式的练习示例。
格式: grep [选项] 匹配模式 [文件]...
常用的选项:
-i:忽略大小写
-v:取反匹配(全部)
-w:匹配单词
-q:静默匹配,不将结果显示在屏幕上
下面来介绍一些练习的指令
创建一个名为 test.txt 的文件,并在里面写上足够的内容
- 过滤文件中 带 the 的行
grep the test.txt
- 过滤文件中带 the 的行,不区分大小写
grep -i the test.txt
- 过滤包含数字的行
grep "[0-9]" test.txt
grep -P "\\d" test.txt
保姆级Java入门练习教程,附代码讲解,小白零基础入门必备(建议收藏)
肝了 10 万字 ,Go 语言保姆级编程教程2021最新版(建议收藏)
肝了 10 万字 ,Go 语言保姆级编程教程2021最新版(建议收藏)
JavaScript保姆级教程 ——— 重难点详细解析(万字长文,建议收藏)