shell基础
# 语言简介
# 基础知识
在计算机科学中,shell
就是一个命令解释器。 shell
是位于操作系统和应用程序之间,是他们二者最主要的接口,shell
负责把应用程序的输入命令信息解释给操作系统,将操作系统指令处理后的结果解释给应用程序。一句话,shell
就是在操作系统和应用程序之间的一个命令翻译工具。
类型 | 说明 |
---|---|
图形界面shell | 图形界面shell就是我们常说的桌面 |
命令行式shell | windows系统:cmd.exe命令提示字符;linux系统:sh、csh、ksh、bash ... |
我们常说的shell是命令行式的shell,在工作中常用的是linux系统下的
bash
。
# 简单介绍
查看当前系统的shell类型
[root@manager ~]# echo $SHELL
1查看当前系统环境支持的shell
[root@manager ~]# cat /etc/shells /usr/bin/sh /usr/bin/bash /usr/sbin/nologin
1
2
3
4更改默认的shell
chsh <用户名> -S <新shell>
1使用方式
方式 | 作用 | 特点 |
---|---|---|
手工方式 | 手工敲击键盘,在shell的命令行输入命令,按Enter后,执行通过键盘输入的命令,然后shell返回并显示命令执行的结果。 | 逐行输入命令、逐行进行确认执行 |
脚本方式 | 就是说我们把手工执行的命令a,写到一个脚本文件b中,然后通过执行脚本b,达到执行命令a的效果.当可执行的Linux命令或语句不在命令行状态下执行,而是通过一个文件执行时,我们称文件为shell脚本。 | 执行文件达到批量执行命令的效果 |
shell脚本示例
- 使用脚本的方式来执行一下
#!/bin/bash #这是临时shell脚本 echo 'nihao' echo 'devops'
1
2
3
4- 脚本执行效果
[root@manager ~]# /bin/bash test.sh nihao devops
1
2
3
# 简单实践
# 通用操作
脚本编辑工具
- 常见编辑器是
vi/vim
- 常见编辑器是
脚本命名
- 有意义,方便我们通过脚本名,来知道这个文件是干什么用的。
脚本内容
- 各种可以执行的命令
注释
- 单行注释(#)
- 多行注释(:<<字符...字符)
执行操作
bash /path/to/script-name
或/bin/bash /path/to/script-name
- 脚本文件本身没有可执行权限或者脚本首行没有命令解释器时使用的方法,我们推荐用bash执行。
/path/to/script-name
或./script-name
- 脚本文件具有可执行权限时使用。
source script-name
或. script-name
- 使用
source
或者.
点号,加载shell脚本文件内容,使shell脚本内容环境和当前用户环境一致。使用场景:环境一致性
- 使用
# 开发技巧
- 脚本命名要有意义,文件后缀是
.sh
- 脚本文件首行是而且必须是脚本解释器
#!/bin/bash
- 脚本文件常见执行方式:
bash 脚本名
- 脚本内容执行:从上到下,依次执行
- 脚本文件解释器后面要有脚本的基本信息等内容
- 脚本文件中尽量不用中文注释
- 尽量用英文注释,防止本机或切换系统环境后中文乱码的困扰
- 常见的注释信息:脚本名称、脚本功能描述、脚本版本、脚本作者、联系方式等
- 代码书写优秀习惯
- 成对内容的一次性写出来,防止遗漏。如: ()、{}、[]、''、``、""
- []中括号两端要有空格,书写时即可留出空格,然后再退格书写内容
- 流程控制语句一次性书写完,再添加内容
- 通过缩进让代码易读;(即该有空格的地方就要有空格)
# 变量基础
# 简单介绍
变量包括两部分
- 变量名(不变的)
- 变量值(变化的)
表现样式
- 变量名=变量值
功能定位
- 通过变量名的调用,达到快速执行批量的效果
# 注意事项
- 变量的全称应该称为变量赋值,简称变量。
- 在工作中,我们一般只xx是变量,其实是将这两者作为一个整体来描述了。
- 准确来说,我们一般所说的变量其实指的是变量名。
# shell中的变量分类
分类 | 作用 |
---|---|
本地变量 | 变量名仅仅在当前终端有效 |
全局变量 | 变量名在当前操作系统的所有终端都有效 |
shell内置变量 | shell解析器内部的一些功能参数变量 |
# 变量详解
# 本地变量
- 本地变量就是:在当前系统的某个环境下才能生效的变量
- 作用范围小
- 本地变量包含两种
- 普通变量
- 命令变量
# 普通变量的定义方式
类型 | 样式 | 特点 |
---|---|---|
无引号 | 变量名=变量值 | 变量值必须是一个整体,中间没有特殊字符"="前后不能有空格 |
单引号 | 变量名='变量值' | 原字符输出 |
双引号 | 变量名="变量值" | 变量值先解析,后整合 |
习惯:数字不加引号,其他默认加双引号
# 命令变量的定义方式
类型 | 样式 | 特点 |
---|---|---|
反引号 | 变量名=`命令` | 反引号 |
小括号 | 变量名=$(命令) | $() |
# 执行流程
- 执行``或者$()范围内的命令
- 将命令执行后的结果,赋值给新的变量名A
# 全局变量
在当前系统的所有环境下都能生效的变量,可以基于
env
命令查看表现样式:
export 变量=值
# 基本操作
- 查看
- $变量名、"$变量名"、${变量名}、"${变量名}”
- 取消
unset 变量名
# 内置变量
# 属性含义
符号 | 意义 | 符号 | 意义 |
---|---|---|---|
$0 | 获取当前脚本文件名 | $n | 获取脚本的第n个参数值,样式:$1,${10} |
$# | 获取脚本参数的总个数 | $? | 获取上一个指令的状态返回值(0为成功,非0为失败) |
$* | 获取所有参数,存放到一个字符串中 | $@ | 获取所有参数,存放到一个列表里面 |
$$ | 获取当前程序进程号 | $! | 获取上一个进程的id |
# 演示效果
$0
获取脚本的名称#!/bin/bash # 获取脚本的名称 echo "脚本的名称是:file.sh" echo "脚本的名称是:$0"
1
2
3
4$n
获取位置参数值#!/bin/bash # 获取指定位置的参数 echo "第一个位置的参数是:$1" echo "第二个位置的参数是:$2"
1
2
3
4$#
获取参数总数量#!/bin/bash # 获取当前脚本传入的参数数量 echo "当前脚本传入参数数量是:$#"
1
2
3$?
获取文件执行或者命令执行的返回状态值# bash nihao bash: nihao: No such file or directory # echo $? 127 # ls fi1e1.sh num.sh test.sh weizhi.sh # echo $? 0
1
2
3
4
5
6
7
8$*
vs$@
#!/bin/bash # $*获取到的参数内容放到一个字符串 for arg in "$*";do echo '$*获取到的参数内容: '$arg done # 查看$@获取的元素内容 for arg in "$@";do echo '$@获取到的参数内容: '$arg done
1
2
3
4
5
6
7
8
9
10$$
效果#!/bin/bash
1
#获取当前程序执行时候的进程号 echo '$$ 获取当前程序执行时候的进程号' ```
$!
获取上一条命令的进程号# sleep 15 & [1]8080
1
2$!
获取上一条命令的进程号# echo $! 8080
1
2
# 条件表达式
# 语法格式
- 条件的结果无非就是成立或者不成立,而我们之前所学的$?就可以表示
- 判断条件是否成立的过程我们称为条件判断,他一般有两种表现形式︰
- test条件表达式
- [ 条件表达式 ]
- 注意:需要注意方括号[、]与条件表达式之间至少有一个空格。
- 条件成立,状态返回值是0
- 条件不成立,状态返回值是1
# 简单实践
# 逻辑表达式
符号 | 样式 | 作用 |
---|---|---|
&& | 命令1 &&命令2 | 只有1成功,2才执行 |
|| | 命令1 ||命令2 | 只有1失败,2才执行(1和2只能执行一个) |
示例∶
# [ 1 = 1 ] && echo "条件成立" 条件成立 # [ 1 = 2 ] && echo "条件成立" # # [ 1 = 2 ] || echo "条件不成立" 条件不成立 # [ 1 = 1 ] || echo "条件不成立" #
1
2
3
4
5
6
7
8
9
# 文件表达式
符号 | 样式 | 作用 |
---|---|---|
-f|d|s | -f file_name | 判断文件格式(普通文件|目录|链接文件) |
-r|w|x | -x file_name | 判断文件权限(读写执行) |
示例
# [ -f weizhi.sh ] && echo "是一个文件" 是一个文件 # [ -f weizhi .sddh ] || echo "不是一个文件" 不是一个文件 # [ -d weizhi.sddh ] || echo“不是一个目录" 不是一个目录 # [ -x age.sh ] || echo“文件没有执行权限" 文件没有执行权限
1
2
3
4
5
6
7
8
9
# 一般表达式
判断数字 | 样式 | 特点 | 判断字符串 | 样式 | 特点 |
---|---|---|---|---|---|
eq | 数字1 eq 数字2 | 相等eq,不等ne | == != | str1 == str2 | 字符串内容是否一致 |
gt | 数字1 gt 数字2 | gt大于,小于lt | -z -n | -z str1 | z空,n不空 |
注意:在字符串表达式中,"=="可以简写为"=",但是我们不推荐。
数字示例:
n1 -eq n2 # 相等 n1 -ne n2 # 不等于 n1 -ge n2 # 大于等于 n1 -gt n2 # 大于 n1 -lt n2 # 小于 n1 -le n2 # 小于等于
1
2
3
4
5
6字符示例︰
[ a == a ] echo $? [ a != a ] echo $? [ -z daf ] [ ! -z daf ] [ -n daf ] [ ! -n daf ]
1
2
3
4
5
6
7
8
9
10
# 逻辑组合
# 条件组合
!
非运算,表达式结果取反。示例[ ! false ]返回true。-o
或运算,多个表达式只要有一个为true,整体为true。示例[ $a -lt 20 -o $b -gt 100]
-a
与运算,多个表达式都为true,整体为true。示例[ $a -lt 20 -a $b -gt 100 ]
非运算实践
# a=5 # [ $a -gt 5 ] # echo $? 1 # [ ! $a -gt 5 ] # echo $? 0
1
2
3
4
5
6
7或运算实践
# a=5 # b=7 # [ $a -gt 3 -o $b -lt 7 ] # echo $? 0 # [ $a -lt 3 -o $b -lt 7 ] # echo $? 1
1
2
3
4
5
6
7
8与运算实践
# a=5 # b=7 # [ $a -gt 3 -a $b -lt 7 ] # echo $? 1 # [ $a -gt 3 -a $b -eq 7 ] # echo $? 0
1
2
3
4
5
6
7
8
# 逻辑进阶
所谓的逻辑进阶,说的还是&&和||,只不过说的是完整写法,结果是整体的状态值
[[ 条件1 && 条件2 ]]
只有所有条件为真,整体结果为真。[[ 条件1 || 条件2 ]]
只要有一个条件为真,整体结果为真。
其实,它也可以理解为-a或者-o 的另外一种写法。
或运算实践
# a=5 # b=7 # [[ $a -gt 3 || $b -lt 7 ]]# echo $? 0 # [[ $a -lt 3 || $b -lt 7 ]]# echo $? 1
1
2
3
4
5
6与运算实践
# a=5 # b=7 # [[ $a -gt 3 8& $b -lt 7 ]]# echo $? 1 # [[ $a -gt 3 && $b -eq 7 ]]# echo $? 0
1
2
3
4
5
6
# 计算表达式
需求:我们需要在 shell 内部对数据进行普通的数据计算操作
# 基本语法
方法1:数据运算
$((数据计算))
注意:数据计算表达式不受空格限制
方法2:本身计算
let 变量名=数据计算
注意:数据计算表达式必须在一起,不允许有空格
方法3:数据运算
expr 数据计算
注意:计算的结果不会交给一个值,也不支持变量
2
3
4
5
6
7
8
9
# 简单实践
方法1实践
# echo $((5+1)) 6 # a=5 # echo $((a+=1)) 6
1
2
3
4
5方法2实践
let a=4+3 # echo $a 7
1
2
3方法3实践
# expr 3 + 4 7 # expr $a + 1 8 # a=10 # b=20 # val=`expr $a + $b` # echo $val 30
1
2
3
4
5
6
7
8
9
10
11
# 字符串基本操作
# 长度计算
获取字符串的内容长度
方法
方法1: ${#string} 方法2: expr length "$string" 方法3: echo $string | awk '{print length}'
1
2
3简单实践
# a=charsetstring # echo ${#a} 13 # expr length "$a" 13 # echo "$a" | awk '{print length}' 13
1
2
3
4
5
6
7
# 提取内容
我们需要字符串内部的部分数据
方法
${string:偏移量:截取长度} 注意: 偏移量 指的是列表的索引值,即默认第一个字符的索引值是0 截取长度表示要截取的字符串长度,如果为负值,表示反向截取
1
2
3
4简单实践
# echo $a charsetstring # echo ${a:3:5} rsets # echo ${a:1:-1} # 获取2~最后位置的元素 harsetstrin # echo ${a:2} # 获取2~最后位置的元素 arsetstring # echo ${a::-2} # 从首位到倒数第二位 charsetstri
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 转换操作
对字符串内容进行简单的大小写更改
方法
${string^^} 全部转换成大写 ${string,,} 全部转换成小写
1
2简单实践
# c=SetCharsetString # echo ${c^^} SETCHARSETSTRING # echo ${c,,} setcharsetstring
1
2
3
4
5
6
7
# 字符串进阶
# 删除操作
删除或者替换指定的信息
常见语法
${string#字符串} # 删除string内部头部存在匹配的字符串的话,删除头部的字符 ${string##字符串正则} # 贪婪模式,删除string内部所有匹配到的信息 ${string%字符串} # 删除string内部尾部存在匹配的字符串的话,删除尾部的字符 ${string%%字符串正则} # 贪婪模式,删除string内部所有匹配到的信息 ${string/字符串正则} # 删除首次匹配到的内容 ${string//字符串正则} # 删除全部匹配到的内容 ${string/#字符串正则} # 删除匹配到的头部内容,等同于${string#字符串} ${string/%字符串正则} # 删除匹配到的尾部内容,等同于${{string%字符串}
1
2
3
4
5
6
7
8
9
10
11删除头部信息
# echo $b setcharsetstring # echo ${b#set} charsetstring # echo ${b#char} setcharsetstring # echo ${b##s*t} ring
1
2
3
4
5
6
7
8
9
10
11删除尾部信息
# echo ${b%ring} setcharsetst # echo ${b%%r*g} setcha
1
2
3
4
5删除操作
# echo ${b/set} charsetstring # echo ${b//set} charstring # echo ${b/#set} charsetstring # echo ${b/%ing} setcharsetstr
1
2
3
4
5
6
7
8
9
10
11
# 替换操作
修改字符串内部的部分信息,将其替换为指定的内容
语法
${string/正则表达式/替换内容} # 将正则表达式 第一次 匹配到的信息替换成指定的信息 ${string//正则表达式/替换内容} # 将正则表达式 全部 匹配到的信息替换成指定的信息
1
2替换实践
# echo $b setcharsetstring # echo ${b/set/SET} SETcharsetstring # echo ${b//set/SET} SETcharSETstring
1
2
3
4
5
6
7
8
# 赋值操作
在编写脚本的时候,我们需要进行对某些变量进行临时性或即时性的赋值操作,从而满足对应的需求。
语法
${string:-value} # 如果变量string为空或者未设置,则返回value的值:否则返回string自己的值 ${string:=value} # 如果变量string为空或者未设置,则将value的值交给string:否则返回string自己的值 ${string:+value} # 如果变量string有内容,则返回value的值 ${string:?value} # 如果变量string为空或者未设置,则返回value的值到标准错误输出strout
1
2
3
4:-
实践# echo $a charsetstring # echo ${a:-666} charsetstring #a="" # echo ${a:-666} 666 # echo ${a}
1
2
3
4
5
6
7
8
9
10
11
12:=
实践# echo ${aa} # echo ${aa:=666} 666 # echo ${aa} 666 # echo ${aa:=777} 666
1
2
3
4
5
6
7
8
9
10:+
实践# echo ${aa} 666 # echo ${aa:+888} 888 # aa="" # echo ${aa:+888}
1
2
3
4
5
6
7
8
9:?
实践# echo ${aa:?'error'} -bash: aa: error #aa="aaa" # echo ${aa:?'error'} aaa
1
2
3
4
5
6
# 数组操作
# 基础知识
- bash支持一维数组(不支持多维数组)
- 没有限定数组的大小
- 数组元素的下标由0开始编号
- 获取数组中的元素要利用下标
- 下标可以是整数或算术表达式,其值应大于或等于0
- 在shell中,数组也称为关联数组,因为它是将变量名和值关联在一起了。
# 作用
- 将一个范围的数据放在一起,进行批量管理
- 分类:数组按照表现形式上,可以划分为:
- 关联数组(普通数组)–所有元素按照顺序依次排列
- 稀疏数组–元素的不按照顺序排列,可以有间隔,即1 3 5等,中间找不到2 4
# 常见操作
创建数组
定制空数组 declare -a array_name
定制数组 array_name=(value1...valuen)
定制数组(单值) array_name[0]=value0
定制稀疏数组 array_name=([index1]=v1 [index3]=v3 [index7]=v7)
查看数组
获取具体内容 ${array_name[index]}
获取长度 ${#array_name[index]}
获取内容的部分信息 ${array_name[index]:pos:length}
获取所有索引 ${!array_name[@]}
更改数组
更改具体值 array_name[index]=值
部分内容替换 ${array_name[index]/原内容/新内容}
删除数组
删除具体值 unset array_name[index]
删除整个数组 unset array_name
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 简单实践
创建实践
# 标准创建 array_name=(value0 value1 value2 value3) # 逐个增加 array_name[0]=value0 array_name[1]=value1 array_name[2]=value2 # 稀疏数组 array_name=([0]=v1 [2]=v2 [4]=v4) # 技巧 – 把指定目录下的所有文件动态添加到数组中 fi1e_array=($(ls /tmp/))
1
2
3
4
5
6
7
8
9
10
11
12查看实践
# 查看指定位置元素 echo ${array_name[1]} # 注意:索引的值是从О开始计算的 # 查看所有位置元素 echo ${array_name[@]} echo ${array_name[*]} # 获取所有位置的索引号 echo ${!array_name[*]} # 获取元素数量 echo ${#array_name[1]} echo ${#array_name[@]} echo ${#array_name[*]} # 获取元素的部分信息 echo ${array_name[2]:0:2}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18更改实践
# 单值更改 array_name[1]=444 echo ${array_name[1]} # 内容更改 echo ${array_name[2]} echo ${array_name[2]/va/hahhah}
1
2
3
4
5
6
7删除实践
# 删除单个元素 unset array_name[1] # 删除整个数组 unset array_name
1
2
3
4
5
# 配置文件
简单了解bash启动过程中涉及到的主要配置文件
bash涉及到的几个重要文件
系统级别: /etc/profile 操作系统级别 /etc/profile.d/*.sh 系统软件级别 个人级别: (优先级从上到下,一般只会有最后一个) ~/.bash_profile ~/.bash_login ~/.profile bash级别: ~/.bashrc 定制用户环境
1
2
3
4
5
6
7
8
9