shell的定义
在计算机科学中,Shell就是一个命令解释器。
shell是位于操作系统和应用程序之间,是他们二者最主要的接口,shell负责把应用程序的输入命令信息解释给操作系统,将操作系统指令处理后的结果解释给应用程序。
查看系统shell信息
查看当前系统的shell类型
echo $SHELL
查看当前系统环境支持的shell
[root@linux-node1 ~]# cat /etc/shells
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
shell脚本定义
当可执行的Linux命令或语句不在命令行状态下执行,而是通过一个文件执行时,我们称文件为shell脚本。
创建脚本
创建脚本的常见编辑器是 vi/vim.
shell脚本的命名简单来说就是要有意义
脚本示例
#!/bin/bash
# 这是临时shell脚本
echo ‘nihao’
echo ‘itcast’
脚本执行效果
[root@linux-node1 ~]# /bin/bash itcast.sh
nihao
itcast
注释内容
除了首行的#不是注释外,其他所有行内容,只要首个字符是#,那么就表示该行是注释
#!/bin/bash
echo '1'
# echo '2' # 这一行就表示注释
echo '3'
多行注释有两种方法::<<! ... ! 和 :<<字符 ... 字符
#!/bin/bash
echo '1'
:<<! echo '2'
echo '3'
echo'4'
!
echo'5'
shell执行的方式
Shell脚本的执行通常可以采用以下几种方式
bash /path/to/script-name 或 /bin/bash /path/to/script-name (强烈推荐使用)
/path/to/script-name 或 ./script-name (当前路径下执行脚本)
source script-name 或 . script-name (注意“.“点号)
脚本开发规范
1.脚本命名有意义,后缀是.sh
2.脚本文件首行是脚本解释器:#!/bin/bash
3.脚本解释器后面要有脚本的基本信息,尽量用英文(脚本名称,脚本功能,脚本版本,脚本作者,联系方式等)
4.脚本文件常见执行方式:bash 脚本名
5.脚本内容执行:从上到下依次执行
6.优秀的书写习惯
7.通过缩进让代码易读(该有的空格就要有)
变量
本地变量
方式一:变量=变量值
变量值必须是一个整体,中间没有特殊字符。
方式二:变量名=‘变量值’
我看到的内容,我就输出什么内容
方式三:变量名=“$变量名 变量值”
如果变量值中有可解析的变量,先解析($变量名)然后将结果和其他内容组合到一起,赋给变量名
命令变量定义方式
方式一:
变量名=命令 注意:`是反引号
方式二:
变量名=$(命令)
全局变量
全局变量就是:在当前系统的所有环境下都能生效的变量
查看全局变量命令:
env 只显示全局变量
定义全局变量
方法一:
变量=值
export 变量
方法二:
export 变量=值
变量查看和取消
查看
方式一:
$变量名
方式二:
"$变量名"
方式三:
${变量名}
方式四:
"${变量名}"
标准写法
取消变量
unset 变量名
也可以删除本地变量
shell内置变量
脚本文件有关
$0 获取当前执行的脚本文件名,包括脚本路径
#!/bin/bash
# 获取脚本的名称
echo "我脚本的名称是: file.sh"
echo "我脚本的名称是:$0"
$# 获取当前脚本传入参数的数量
$n 获取当前脚本传入的第n个位置的参数
#!/bin/bash
# 获取当前脚本传入的参数数量
echo "当前脚本传入的参数数量是: $#"
# 获取指定位置的参数
echo "第一个位置的参数是: $1"
echo "第二个位置的参数是: $2"
echo "第三个位置的参数是: $3"
echo "第四个位置的参数是: $4"
$? 获取文件执行或者命令执行的返回状态值
# bash nihao
bash: nihao: No such file or directory
# echo $?
127
# ls
file1.sh num.sh test.sh weizhi.sh
# echo $?
0
字符串精确截取
格式:${变量名:起始位置:截取长度}
示例:
${file:0:5} 从第1个字符开始,截取5个字符
${file::5} 从第1个字符开始,截取5个字符
${file:5:5} 从第6个字符开始,截取5个字符
${file:5} 从第6个字符开始,截取后面所有的字符
${file:0-5} 从倒数第5个字符开始,截取后面所有的字符
${file:0-6:3} 从倒数第6个字符开始,截取之后的3个字符
默认值相关
格式一:
变量a如果有内容,那么就输出a的变量值
变量a如果没有内容,那么就输出默认的内容
${变量名:-默认值}
如果我输入的参数为空,那么输出内容是 "您选择的套餐是: 套餐 1"
如果我输入的参数为n,那么输出内容是 "您选择的套餐是: 套餐 n"
#!/bin/bash
# 套餐选择演示
a="$1"
echo "您选择的套餐是: 套餐 ${a:-1}"
格式二:
无论变量a是否有内容,都输出默认值
${变量名+默认值}
不管我说国家法定结婚年龄是 多少岁,都输出 国家法定结婚年龄(男性)是 22 岁
#!/bin/bash
# 默认值演示示例
a="$1"
echo "国家法定结婚年龄(男性)是 ${a+22} 岁"
表达式
区分不同的情况以确定执行何种操作
测试语句
Shell环境根据命令执行后的返回状态值($?)来判断是否执行成功,当返回值为0,表示成功,值为其他时,表示失败。
格式A:test 条件表达式
格式B:[ 条件表达式 ]
后者为常用,但后者需要注意方括号[ ]与条件表达式之间至少有一个空格
条件表达式
逻辑表达式:一般用于判断多个条件之间的依赖关系
命令1 && 命令2
如果命令1执行成功,那么我才执行命令2 -- 夫唱妇随
如果命令1执行失败,那么命令2也不执行
# [ 1 = 1 ] && echo "条件成立"
条件成立
# [ 1 = 2 ] && echo "条件成立"
#
命令1 || 命令2
如果命令1执行成功,那么命令2不执行 -- 对着干
如果命令1执行失败,那么命令2执行
# [ 1 = 2 ] || echo "条件不成立"
条件不成立
# [ 1 = 1 ] || echo "条件不成立"
#
文件表达式
-f 判断输入内容是否是一个文件
# [ -f weizhi.sh ] && echo "是一个文件"
是一个文件
# [ -f weizhi.sddh ] || echo "不是一个文件"
不是一个文件
-d 判断输入内容是否是一个目录
# [ -d weizhi.sddh ] || echo "不是一个目录"
不是一个目录
# mkdir nihao
# [ -d nihao ] && echo "是一个目录"
是一个目录
-x 判断输入内容是否可执行
# [ -x age.sh ] || echo "文件没有执行权限"
文件没有执行权限
# [ -x test.sh ] && echo "文件有执行权限"
文件有执行权限
数值操作符
n1 -eq n2 相等
n1 -gt n2 大于
n1 -ge n2 大于等于
n1 -lt n2 小于
n1 -le n2 小于等于
n1 -ne n2 不等于
字符串比较
str1 == str2 str1和str2字符串内容一致
str1 != str2 str1和str2字符串内容不一致,!表示相反的意思
root@ubuntu:~# [ a == a ]
root@ubuntu:~# echo $?
0
root@ubuntu:~# [ a != a ]
root@ubuntu:~# echo $?
1
计算表达式
计算表达式,简单来说就是对具体的内容进行算数计算
方式一:
$(()) $(( 计算表达式 ))
格式:a=$((变量名a+1))
注意:表达式范围内,空格不限制
root@ubuntu:~# echo $((100/5))
20
方式二:
let let 计算表达式
格式:let 变量名a=变量名a+1
注意:表达式必须是一个整体,中间不能出现空格等特殊字符
root@ubuntu:~# i=1
root@ubuntu:~# let i=i+7
root@ubuntu:~# echo $i
8
注意:
$(())中只能用+-*/和()运算符,并且只能做整数运算
linux常见符号
重定向符号
在shell脚本中有两种常见的重定向符号 > 和 >>
>符号表示将符号左侧的内容,以覆盖的方式输入到右侧文件中
查看文件内容
admin-1@ubuntu:~$ cat file.txt
nihao
使用重定向符号给文件中增加内容
admin-1@ubuntu:~$ echo "file1.txt" > file.txt
再次查看文件内容
admin-1@ubuntu:~$ cat file.txt
file1.txt
>> 符号 表示将符号左侧的内容,以追加的方式输入到右侧文件的末尾行中
查看文件内容
admin-1@ubuntu:~$ cat file.txt
file1.txt
使用重定向符号给文件中增加内容
admin-1@ubuntu:~$ echo "file2.txt" >> file.txt
再次查看文件内容
admin-1@ubuntu:~$ cat file.txt
file1.txt
file2.txt
管道符 |
命令1 | 命令2
管道符左侧命令1 执行后的结果,传递给管道符右侧的命令2使用
查看当前系统中的全局变量SHELL
admin-1@ubuntu:~$ env | grep SHELL
SHELL=/bin/bash
后台展示符号 &
& 就是将一个命令从前台转到后台执行
格式:命令 &
admin-1@ubuntu:~# sleep 4
界面卡住4秒后消失
admin-1@ubuntu:~# sleep 10 &
[1] 4198
admin-1@ubuntu:~# ps aux | grep sleep
root 4198 0.0 0.0 9032 808 pts/17 S 21:58 0:00 sleep 10
root 4200 0.0 0.0 15964 944 pts/17 S+ 21:58 0:00 grep --color=auto sleep
Ctrl+Z 让当前任务转入到后台并停止
jobs 查看后台任务
fg 让后台进程转入到前台执行
bg 让后台停止的任务继续在后台执行
全部信息符号 2>&1
1 表示正确输出的信息
2 表示错误输出的信息
2>&1 代表所有输出的信息
标准正确输出示例
cat nihao.txt 1>> zhengque
标准错误输出示例
dsfadsfadsfa 2>> errfile
linux系统垃圾桶
/dev/null 是linux下的一个设备文件,
这个文件类似于一个垃圾桶,特点是:容量无限大
常见命令
grep命令
grep命令是我们常用的一个强大的文本搜索命令
格式:grep [参数] [关键字] <文件名>
-c:只输出匹配行的计数
-n:显示匹配行及行号
-v:显示不包含匹配文本的所有行
-i:不区分大小写
sed命令
sed行文件编辑工具。以行为单位
命令格式:sed [参数] '<匹配条件> [动作]' [文件名]
参数
参数为空:表示sed的操作效果,实际上不对文件进行编辑
-i:表示对文件进行编辑
匹配条件
关键字匹配格式:'/关键字/'
注意:隔离符号/可以更换成@、#、!等符号
数字行号匹配
动作
-a:在匹配到的内容下一行增加内容
-i:在匹配到的内容上一行增加内容
-d:删除匹配的内容
-s:替换匹配到的内容
上面的动作应该在参数为-i的时候使用,不然无效果
替换命令
命令格式:sed -i [替换格式] [文件名]
替换命令的写法: 's#原内容#替换后内容#'
原内容
admin-1@ubuntu:~$ cat sed.txt
nihao sed sed sed
nihao sed sed sed
nihao sed sed sed
替换每行 首个匹配内容:
替换首每行的第1个sed为SED
admin-1@ubuntu:~$ sed -i 's#sed#SED#' sed.txt
admin-1@ubuntu:~$ cat sed.txt
nihao SED sed sed
nihao SED sed sed
nihao SED sed sed
替换全部匹配内容:
替换全部sed为SED
admin-1@ubuntu:~$ sed -i 's#sed#SED#g' sed.txt
admin-1@ubuntu:~$ cat sed.txt
nihao SED SED SED
nihao SED SED SED
nihao SED SED SED
指定行号替换首个匹配内容:
替换第2行的首个SED为sed
admin-1@ubuntu:~$ sed -i '2s#SED#sed#' sed.txt
admin-1@ubuntu:~$ cat sed.txt
nihao SED SED SED
nihao sed SED SED
nihao SED SED SED
首行指定列号替换匹配内容:
替换每行的第2个SED为sed
admin-1@ubuntu:~$ sed -i 's#SED#sed#2' sed.txt
admin-1@ubuntu:~$ cat sed.txt
nihao SED sed SED
nihao sed SED sed
nihao SED sed SED
指定行号列号匹配内容:
sed -i '行号s#原内容#替换后内容#列号' 文件名
替换第3行的第2个SED为sed
admin-1@ubuntu:~$ sed -i '3s#SED#sed#2' sed.txt
admin-1@ubuntu:~$ cat sed.txt
nihao SED sed SED
nihao sed SED sed
nihao SED sed sed
增加操作
在指定行号的 下一行 增加内容
格式:sed -i '行号a\增加的内容' 文件名
admin-1@ubuntu:~$ sed -i '2a\zengjia-2' sed.txt
admin-1@ubuntu:~$ cat sed.txt
nihao SED sed SED
nihao sed SED sed
zengjia-2
nihao SED sed sed
如果增加多行,可以在行号位置写个范围值,彼此间使用逗号隔开,例如
sed -i '1,3a\增加内容' 文件名
admin-1@ubuntu:~$ sed -i '1,3a\tongshi-2' sed.txt
admin-1@ubuntu:~$ cat sed.txt
nihao SED sed SED
tongshi-2
nihao sed SED sed
tongshi-2
zengjia-2
tongshi-2
nihao SED sed sed
在指定行号的 当行 增加内容
格式:sed -i '行号i\增加的内容' 文件名
admin-1@ubuntu:~$ sed -i '1i\insert-1' sed.txt
admin-1@ubuntu:~$ cat sed.txt
insert-1
nihao SED sed SED
tongshi-2
nihao sed SED sed
tongshi-2
zengjia-2
tongshi-2
nihao SED sed sed
删除操作
指定行号删除
格式:sed -i '行号d' 文件名
删除第4行内容
admin-1@ubuntu:~$ sed -i '4d' sed.txt
admin-1@ubuntu:~$ cat sed.txt
insert-1
nihao SED sed SED
tongshi-2
tongshi-2
zengjia-2
tongshi-2
nihao SED sed sed
如果删除多行,可以在行号位置多写几个行号,彼此间使用逗号隔开,例如
sed -i '1,3d' 文件名
admin-1@ubuntu:~$ sed -i '3,5d' sed.txt
admin-1@ubuntu:~$ cat sed.txt
insert-1
nihao SED sed SED
tongshi-2
nihao SED sed sed
awk
awk是一个功能非常强大的文档编辑工具,它不仅能一行为单位还能以列为单位处理文件。
命令格式:awk [参数] ' [动作] ' [文件名]
常见参数:-F 指定行的分隔符
常见动作:
print 显示内容
$0 显示当前行所有内容
$n 显示当前行的第n列内容,如果存在多个$n,他们之间使用逗号隔开
常见内置变量
FILENAME 当前输入文件的文件名,该变量是只读的
NR 指定显示行的行号
NF 输出 最后一列的内容
OFS 输出格式的列分隔符,缺省是空格
FS 输入文件的列分融符,缺省是连续的空格和Tab
模板文件内容
admin-1@ubuntu:~$ cat awk.txt
nihao awk awk awk
nihao awk awk awk
打印指定列内容
打印第1列的内容
admin-1@ubuntu:~$ awk '{print $1}' awk.txt
nihao
nihao
指定行打印内容
打印第一行第1和第3列内容
admin-1@ubuntu:~$ awk 'NR==1 {print $1,$3}' awk.txt
nihao awk
指定隔离分隔符,查看内容
admin-1@ubuntu:~$ cat linshi.txt
root:x:0:0:root:/root:/bin/bash
admin-1@ubuntu:~$ awk -F ':' '{print $1,$7}' linshi.txt
root /bin/bash
设置显示分隔符,显示内容
admin-1@ubuntu:~$ awk 'BEGIN{OFS=":"} {print NR,$0}' awk.txt
1:nihao awk awk awk
2:nihao awk awk awk
find命令
命令格式:
find [路径] [参数] [关键字]
参数详解
-name 按照文件名查找文件。
-perm 按照文件权限来查找文件。
-user 按照文件属主来查找文件。
-group 按照文件所属的组来查找文件。
-type 查找某一类型的文件,诸如:
b - 块设备文件 d - 目录 c - 字符设备文件
p - 管道文件 l - 符号链接文件 f - 普通文件。
-size n:[c] 查找文件长度为n块的文件,带有c时表示文件长度以字节计。
-depth:在查找文件时,首先查找当前目录中的文件,然后再在其子目录中查找。
-mindepth n:在查找文件时,查找当前目录中的第n层目录的文件,然后再在其子目录中查找。
! : 表示取反
在当前系统中查找一个叫awk的文件
admin-1@ubuntu:~$ sudo find /home/admin-1/ -name "awk.txt"
/home/admin-1/awk.txt
在当前系统中查找文件类型为普通文件的文件
admin-1@ubuntu:~$ find /tmp -type f
/tmp/.X0-lock
/tmp/vgauthsvclog.txt.0
/tmp/unity_support_test.0
/tmp/config-err-4igbXW
流程控制
单分支if语句
语法格式
if [ 条件 ]
then
指令
fi
单一条件,只有一个输出
#!/bin/bash
# 单if语句的使用场景
if [ "$1" == "nan" ]
then
echo "您的性别是 男"
fi
双分支if语句
语法格式
if [ 条件 ]
then
指令1
else
指令2
fi
一个条件,两种结果
#!/bin/bash
# 单if语句的使用场景
if [ "$1" == "nan" ]
then
echo "您的性别是 男"
else
echo "您的性别是 女"
fi
多分支if语句
语法格式
if [ 条件 ]
then
指令1
elif [ 条件2 ]
then
指令2
else
指令3
fi
n个条件,n+1个结果
#!/bin/bash
# 单if语句的使用场景
if [ "$1" == "nan" ]
then
echo "您的性别是 男"
elif [ "$1" == "nv" ]
then
echo "您的性别是 女"
else
echo "您的性别,我不知道"
fi
多if语句生产场景: 服务的启动
需求:要求脚本执行需要有参数,通过传入参数来实现不同的功能。
参数和功能详情如下:
参数 执行效果
start 服务启动中...
stop 服务关闭中...
restart 服务重启中...
* 脚本 X.sh 使用方式 X.sh [ start|stop|restart ]
脚本内容
admin-1@ubuntu:/data/scripts/python-n# cat if.sh
#!/bin/bash
# 多if语句的使用场景
if [ "$1" == "start" ]
then
echo "服务启动中..."
elif [ "$1" == "stop" ]
then
echo "服务关闭中..."
elif [ "$1" == "restart" ]
then
echo "服务重启中..."
else
echo "$0 脚本的使用方式: $0 [ start | stop | restart ]"
fi
case选择语句
case 语句格式
case 变量名 in
值1)
指令1
;;
值2)
指令2
;;
值3)
指令3
;;
esac
注意:
首行关键字是case,末行关键字esac
选择项后面都有 )
每个选择的执行语句结尾都有两个分号;
case语句示例
场景:在多if语句的基础上对脚本进行升级
需求:要求脚本执行需要有参数,通过传入参数来实现不同的功能。
参数和功能详情如下:
参数 执行效果
start 服务启动中...
stop 服务关闭中...
restart 服务重启中...
* 脚本 X.sh 使用方式 X.sh [ start|stop|restart ]
脚本内容:
# cat case.sh
#!/bin/bash
# case语句使用场景
case "$1" in
"start")
echo "服务启动中..."
;;
"stop")
echo "服务关闭中..."
;;
"restart")
echo "服务重启中..."
;;
*)
echo "$0 脚本的使用方式: $0 [ start | stop | restart ]"
;;
esac
for循环语句
语法格式
for 值 in 列表
do
语句执行
done
示例:遍历文件
#!/bin/bash
# for语句的使用
for i in $(ls /root)
do
echo "${i}"
done
while循环语句
语法格式
while 条件
do
执行语句
done
条件类型:命令、[[字符串表达式]]、((数字表达式))
示例
#!/bin/bash
# while的示例
a=1
while [ "${a}" -lt 5 ]
do
echo "${a}"
a=$((a+1))
done
until循环语句
语法格式
until 条件
do
执行语句
done
条件类型:命令、[[字符串表达式]]、((数字表达式))
示例
#!/bin/bash
# until的示例
a=1
until ["${s}" -eq 5]
do
echo "${a}"
done
函数
定义函数格式:
函数名(){
函数体
}
调用函数:
函数名
传参函数格式:
传参数
函数名 参数
函数体调用参数:
函数名(){
函数体 $n
}
示例
#!/bin/bash
# 函数的使用场景二
dayin(){
echo "wo de mingzi shi $1"
echo "wo de mingzi shi $2"
echo "wo de mingzi shi $3"
}
dayin 111 df dfs