什么是shell?
是 在linux内核与用户直接的解释器程序; 通常指/bin/bash; 相当于操作系统的“外壳”。
怎么使用shell? shell的使用方式?
1. 命令行 ==交互式; 逐条解释执行,效率低
2. 脚本 == 非交互式; 批量执行,效率高; 方便在后台静悄悄地运行。
怎么切换shell ?怎么使用某个特定shell?
1. 通过usermod , chsh 更改登录的shell
2. 手动执行目标shell程序
/bin/sh //多数unix默认使用的shell ; /bin/bash //多数Linux默认使用的shell; .......
命令: history 命令
!78 //执行理事记录中的第78条命令
!str //执行最后一次以str开头的历史命令
交互式硬件设备
标准输入: 从该设备接收用户输入的数据
标准输出: 通过该设备向用户输出数据
标准错误: 通过该设备报告执行中的出错信息
类型 | 设备文件 | 文件描述符 | 默认设备 |
标准输入 | /dev/stdin | 0 | 键盘 |
标准输出 | /dev/stdout | 1 | 显示器 |
标准错误输出 | /dev/stderr | 2 | 显示器 |
重定向操作: 改变标准输入/输出/错误输出的方向。
类型 | 操作符 | 用途 |
重定向输入 | < | 将文本输入来源由键盘改为指定的文件 |
重定向输出 | > >> |
将命令行的正常执行输出保存到文件,而不是直接直接显示在屏幕上 与> 类似,但操作是追加而不是覆盖 |
重定向错误 | 2> 2>> |
将命令行的错误输出信息保存到文件中,而不是直接输出到屏幕上 与2>类似,但操作是追加而不是覆盖 |
混合重定向 | &> | 相当于> 和 2>, 覆盖到同一个文件 |
什么是shell脚本?
写好的执行语句,能够完成特定任务的文件
创建脚步的步骤? 脚本创建三步走
1. 创建文本文件; 2. 添加可执行的脚步语句; 3. 添加x 执行权限。
脚本构成? 规范的脚步构成?
1. #!//脚本声明(使用哪种解释器)
2. # //注释信息(步骤, 思路,用途,变量含义等)
3. 可执行语句
脚本怎么执行? 脚本执行有哪几种方式?
1. 作为命令 /命令字; 指定脚本文件的路径,前提是有x 权限
2. 作为“参数”; 不要求有 x 权限
sh 脚本路径
source 脚本文件路径
. 脚本文件路径
shell脚本怎么调试?
1. 直接观察执行中的输出,报错信息, 2 通过 sh -x 开启调试模式, 3在可能出错地方设置 echo 断点
Shell变量
变量的设置和取消
定义赋值变量: 变量名=变量值;
注意事项:
1. 等号两边不要有空格
2. 若指定的变量名已存在,相当于为此变量重新赋值
3. 变量名由字母/数字/下划线组成,区分大小写;不能以数字开头
如:
# X=12
# var1=CentOS
查看变量
应用变量值 : $变量名
查看变量值: echo $变量名, echo ${变量名} //变量名易混淆时,以{}界定; 未定义的变量取不到值
#echo $var16.5, ${var1}6.5
取消变量
手动取消: unset 变量名。。如:
# unset X
退出shell环境时,变量会自动失效。
Shell变量的分类?
1. 储存类型: 整数型, 浮点型,双精度浮点型, 字符型
2. 使用类型:
环境变量: 通常都是大写,有系统维护,只有个别变量,用户可以直接更改
预定义变量: 位置变量: bash内置,存储执行脚本时提供的参数
预定义变量: bash内置,可直接调用,但不能直接赋值或修改
自定义变量: 由用户自主设置,修改及使用
环境变量:
1. 配置文件: /etc/profile ; ~/.bash_profile
2. 相关操作;
# env //列出所有的环境变量
#set //列出所有变量
3. 常见的环境变量
PWD, PATH , USER, LOGNAME, UID , SHELL, HOME, PS1, PS2
预定义变量:
$0 //当前所在的进程名或 脚本名
$$ //当前进程的PID号
$? //命令执行后的返回状态, 0表示正常, 1或其他值表示异常。
$# //已加载的位置变量的个数
$* //所有位置变量的值
位置变量 : $n 或${n} //n为序号,在执行脚本时提供的命令后参数。
扩展赋值操作
有哪三种定界符?它们的区别是什么?
1. 双引号 "" : 允许扩展,以 $ 引用其他变量
2. 单引号 '' : 禁用扩展, 即便$也视为普通字符
3. 反撇号 `` 相当于$() : 将命令的执行输出作为值;但是$()更方便嵌套使用。
# echo "当前用户是:$USER"
#echo '当前用户是: $USER'
#echo 当前的工作目录: $(pwd)
怎么读取标准输入值? read 可以从标准输入中 读取值
read 从键盘读入变量 并完成赋值
格式: read [-p "提示信息"] 变量名 //注意要有空格
-p可选, -t可指定超时秒数
输密码的时候不显示输出内容怎么做到的? 终端显示控制
# stty -echo //关闭终端输出(无显示)
# stty echo //恢复终端输出 (显示)
变量的作用范围? 变量的作用域
1.局部变量
新定义的变量默认只能在当前Shell环境中有效;无法在子Shell环境中使用。
2. 全局变量
在当前Shell及子Shell环境中均有效
怎么定义全局变量: 使用export 可将局部变量声明为全局变量
export 局部变量名[=变量名] //为局部变量添加全局属性
export -n 全局变量名.... //取消指定变量的全局属性
例子:
# SCHOOL="qinghua"
#sh
#echo $SCHOOL
#exit
#export SCHOOL
#sh
#echo $SCHOOL
数值运算: 包括 整数运算, 小数运算
整数运算:
+ - * / %
1. expr 运算工具
格式: expr 整数1 运算符 整数2; //注意运算符两侧要有空格
+ - \* / % //注意乘法要转义,避免被作为Shell通配符
2. 使用 $[] 或 $(()) 表达式
相比expr更方便简便实用:
1.乘法操作 * 无需转义,
2.运算符两侧可以无空格;
3. 应用变量可以省略 $符号;
变量怎么 自增 或自减?
使用 $[] 或者 let 命令
#echo $[i+=2]
#let i++; echo $i
小数的运算
注意: Bash内建机制仅支持整数值运算; expr ; $[] 算式替换不支持小数的运算。
bc //多数Linux 默认安装此工具
quit 退出 ; scale=n 指定小数位数;
bc 的使用; 结合管道向bc发送表达式; 多个表达式分号分隔
# echo "scale=4; $A*56.789;5/3" | bc
小数值的比较
基本用法:
echo "数值1 比较符 数值2" | bc
如果表达式成立,则返回的计算结果为1, 否则返回0
常见比较操作 > >= < <= == !=
#A=12.34; B=56.78
#echo "$A<=$B" | bc
条件测试
test 测试操作
格式: test 选项 参数
或 [ 选项 参数 ] ; //注意要有空格
文件状态测试
[操作符 文件或目录]
操作符 | 含义 |
-e | 判断对象是否存在,若存在则真 |
-d | 判断对象是否为目录, 是则真 |
-f | 判断对象是否为一般文件,是则真 |
-r | 判断对象是否有可读权限,是则为真 |
-w | 判断对象是否有可写权限,是则为真 |
-x | 对象是否有可执行权限,是则为真 |
#[-d /etc/vsftpd]
# echo $?
> 0 //目录存在,测试成立
# [-d /etc/vsftpd] && echo "YES"
整数值比较
[ 整数值1 操作符 整数值2 ]
操作符 | 含义 |
-eq | 等于 Equal |
-ne | 不等于 Not Equal |
-ge | 大于或等于 Greater or Equal |
-le | 小于或等于Lesser or Equal |
-gt | 大于 Greater Than |
-lt | 小于 Lesser Than |
字符串比较
[字符串1 操作符 字符串2]
操作符 | 含义 |
== | 两个字符串相同 |
!= | 两个字符串不相同 |
[操作符 字符串]
操作符 | 字符串 |
-z | 字符串的值为空 |
-n | 字符串的值不为空 |
组合多个条件
逻辑分隔操作
用法:
命令1 操作符 命令2
[条件1] 操作符 [条件2]
操作符 | 含义 |
&& | 给定条件必须都成立,整个测试结果才为真 |
|| | 只要其中一个条件成立,则整个测试结果为真 |
if 选择结构
单分支结构
if 条件测试
then 命令序列
fi
双分支结构
if 条件测试
then 命令序列1
else 命令序列2
fi
多分支结构
if 条件测试1
then 命令序列1
elif 条件测试2
then 命令序列2
else 命令序列n
fi
循环结构
for循环
for 变量名 in 值列表
do
命令序列
done
c语言风格的for循环
for ((初值; 条件; 步长控制))
do
命令序列
done
条件式循环
while 条件测试
do
命令序列
done
until循环
当条件不成立时,循环执行语句序列
until 条件测试
do
命令序列
done
case 分支结构
case 变量值 in
模式1)
命令序列1 ;;
模式2)
命令序列2;;
.....
*)
默认命令序列
esac
函数及中断控制
如何定义函数?
function 函数名{
命令序列
}
函数名(){
命令序列
}
怎么调用函数?
函数名 值1 值2 .. ..
中断,退出及相关指令
break ; 跳出当前所在的循环体,
continue ; 跳过循环体内余下的语句,重新判断条件以判断是否需要执行下一次循环
exit; 退出脚本,默认的返回值是 0
shift ; 用来迁移位置变量,每执行一次,结果如下:丢弃$1,原来的$2 变为$1.
字符串处理
包括1. 字串截取 2. 子串替换 3. 按条件掐头去尾 4. 变量初始值处理
1. 字符串截取:
方法一: 使用${} 表达式
格式: ${var:起始位置:长度} //编号从0开始,可省略
方法二: 使用expr substr
格式: expr substr "$var" 起始位置 长度 //编号从1开始
方法三 : 使用cut工具
格式: echo $val | cut -b 起始位置-结束位置 //编号从1开始
#NM="xiao ming"
#echo ${NM:0:6}
#echo ${NM::6}
#expr substr "$NM" 1 6
#echo $NM | cut -b 1-6
#echo $NM | cut -b -6
路径分割
取目录位置:
格式: dirname "字符串"
格式: basename "字符串" //取文档的基本名称
2. 子串替换
只替换第一个匹配结果
格式 : ${var/old/new}
替换全部匹配结果
格式 : ${var//old/new}
3. 按条件掐头去尾
字符串掐头
从左到右,最短匹配删除
格式: ${变量名#*关键词} //#用来删除头部, *通配符
从左到右,最长匹配删除
格式 : ${变量名##*关键词}
字符串去尾
从右向左,最短匹配删除
格式: ${变量名%关键词*}
从右向左,最长匹配删除
格式: ${变量名%%关键词*}
4. 变量初始值处理
初值的检测及设置
取值, ${var:-word}
//若变量var已存在且非Null,则返回$val 的值; 否则返回子串word,变量var值不变
检测并赋值, ${var:=word}
//若变量var存在且非Null,则返回$var的值;否则返回子串word,并赋值给变量var
Shell数组
变量的类型
变量的值默认均为文本
强制声明类型
格式 : declare 选项 变量名
常见选项
-i //强制为整数
-a //定义为数组
-x //设置为全局变量
-r //设置为只读
定义/赋值数组
方法一, 整体赋值:
格式: 数组名=(值1 值2 .. .. 值n)
方法二,单个元素赋值
格式: 数组名[下标]=值 //下标从0开始
输出数组元素
${数组名[下标]} //获取单个数组元素
${数组名[@]} //获取所有数组元素
${#数组名[@]} //获取数组元素的个数
${数组名[@]:起始下标:元素个数} //获取连续的多个数组元素
${#数组名[下标]} //获取某个数组元素的长度
${数组名[下标]:起始下标:字符数} //截取数组元素值的一部分
expect 简介
可以在shell脚本中,为交互式过程自动输送预先准备的文本或指令,而无需人工干预;触发的依据是预期会出现的特征提示文本。
正则
egrep 过滤工具 //相当于grep -E
以行为单位,逐行进行处理; 默认只输出与表达式匹配的文本行
基本用法:
格式1 : egrep [选项] ‘正则表达式' 文件 .. ..
格式2: 前置命令 | egrep [选项] ‘正则表达式
常用的命令选项
-i //忽略字母大小写
-v //条件取反
-c //统计匹配的行数
-q //静默,无任何输出, 一般用于检测 //看$? 返回值 如果为0,说明有匹配,否则无匹配
-n //显示出匹配结果所在的行号
--color //标红显示匹配字串
基本元字符
类型 | 含义 | 示例 | 说明 | |
^ | 匹配行首 | ^abc | 以abc开头的行 | |
$ | 匹配行尾 | abc$ | 以abc结尾的行 | |
. | 单个字符 | . | 除换行符\n 以外的任意单个字符 |
|
+ | 最少匹配一次 | a+ | 一个或多个连续的a | |
? | 最多匹配一次 | a? (abc)? |
0个或1个a 0个或1个abc |
|
* | 匹配任意次数 | a* (abc)* .* |
0个或多个连续的a 0个或多个连续的abc 任意长度的任意字符 |
|
{n} {n,} |
匹配n次 匹配n-m次 匹配至少n次 |
(ab){3} (ab){1,3} (ab){2,} |
匹配 ababab 匹配ab abab ababab 匹配2个及以上连续的ab |
|
[a|c45_?] | 匹配 a | c 4 5 _ ? | |||
[a-z] | 匹配任意小写字母 | |||
[a-Z0-9] | 匹配任意字母或数字 | |||
[^A-Z] | 匹配非大写字母 | |||
^[^a-z] | 匹配不以小写字母开头的行 |
|||
() | 组合为整体 | ab{1,3} | 匹配ab, abb | |
| | 或者 | root|bin | 匹配root , bin | |
\b | 单词边界 | \broot\b | 匹配单词root, 不匹配keroot, rooty | |
\< | 单词的开头 | \ | 匹配以th开头的单词 | |
\> | 单词的结束 | \ |
作用与 \broot\b相同 |
sed工具
Stream EDitor 流式编辑器; 非交互,基于模式匹配过滤及修改文本; 逐行处理,并将结果输出到屏幕;
可实现对文本的输出,删除,替换,复制,剪切,导入,导出等各种操作。
格式1 : 前置命令 | sed [选项] ‘编辑指令'
格式2: sed [选项] '编辑指令' 文件 .. ..
常见命令选项
-n //屏蔽默认输出(全部文本);按条件输出
-i //直接修改文件内容
-f //使用sed脚本
-e //可指定多个处理动作
-r //启用扩展的正则表达式,若与其他选项一起使用,应作为首个选项
{} //可组合多个命令,以分号分隔
定址符, 即[地址1[,地址2]] //用来指定处理的起,止行数;省略定址符时,默认逐行处理全部文本
基本的处理动作
操作符 | 用途 | 指令示例 |
p | 打印行 | 2,4p 输出第2,3,4行 |
d | 删除行 | 2p;4p 输出第2行, 4行 |
s | 字符串替换 | s/old/new/ 将每行的第一个old替换为new s/old/new/3 将每行的第3个old替换为new s/old/new/g 将所有的old都替换为new 注意: 替换操作的分隔 "/" 可改用其他字符,如# & 等,方便修改文件路径 |
常见的处理操作示例
示例 | 含义解析 |
sed -n 'p' a.txt | 输出所有行,等同于cat a.txt |
sed -n '4p' a.txt | 输出第4行 |
sed -n '4,7p' a.txt | 输出第4~7行 |
sed -n '4,+10p' a.txt | 输出第4行及其后的10行内容 |
sed -n '/^bin/p' a.txt | 输出以bin开头的行 |
sed -n 'p;n' a.txt | 输出奇数行,n表示读入下一行文本 |
sed -n 'n;p' a.txt | 输出偶数行,n表示读入下一行文本 |
sed -n '10,${n;p}' a.txt | 输出从第10行至文件末尾的所有偶数行 |
sed -n '$=' a.txt | 输出文件的行数 |
注意:下面例子只做输出,不更改原文件;若需更改,应添加选项 -i |
|
sed '3,5d' a.txt | 删除第3-5行 |
sed '/xml/d' a.txt | 删除所有包含xml的行 |
sed '/xml/!d' a.txt | 删除不包含xml的行,!符号表示取反 |
sed '/^install/d' a.txt | 删除以install开头的行 |
sed '$d' a.txt | 删除文件的最后一行 |
sed '/^$/d' a.txt | 删除所有空行 |
sed '/^$/{n;/^$/d}' a.txt | 删除重复空行,连续两个空行只保留一个 |
替换文本 | |
sed 's/xml/XML/' a.txt | 将每行中第一个xml替换为XML |
sed 's/xml/XML/3' a.txt | 将每行中的第3个xml替换为XML |
sed 's/xml/XML/g' a.txt | 将所有的xml都替换为XML |
sed 's/xml//g' a.txt | 将所有的xml都删除(替换为空串) |
sed 's/doc/&s/g' a.txt | 将所有的doc都替换为docs,&代表查找串 |
sed '4,7s/^/#/' a.txt | 将4-7行注释掉(行首加#) |
sed 's/^#an/an/' a.txt | 解除以#an开头的行的注释(去掉行首的#号) |
注意: 此例只做输出,不更改原文件(若需要更改,应该添加选项 -i) | |
使用 sed脚本
复杂操作可存为脚本,通过-f调用
格式: sed -f 操作脚本 文件 .. ..
sed文本块处理
应用场景?能做什么?
如何在文本内插入新行?
如何插入多行文本?
如何替换掉指定的整行文本?
操作符 | 用途 | 指令示例 |
i | 行前插入文本 | 2iYY 在第2行之前添加文本行 “YY” 4,7iYY 在第4-7行的每一行前添加文本行 |
a | 行后插入文本 | 2aYY 在第2行后添加文本 /^XX/aYY 在以XX开头的行之后添加文本 |
c | 替换当前行 | 2cYY 将第2行的内容修改为 YY |
处理多行文本
修改后的文本有多行时? 我想插入多行怎么做?
以换行符\n 分隔
或者 使用\ 强制换行
#sed -n '2cXX\nYY' m.txt
sed 高级应用
文件导入导出
操作符 | 用途 | 指令示例 |
r | 读取文件 | 3r b.txt 在第3行下方插入文件b.txt 4,7r b.txt 在第4-7行后插入文件b.txt |
w | 保存到文件 | 3w c.txt 将第3行另存为文件c.txt 4,7w c.txt 将第4-7行另存为文件c.txt |
注意: -r动作应结合-i选项才会存入,否则只能输出
#sed '2r m.txt' reg.txt
#sed -n '/^XX/w d.txt' reg.txt
sed 复制剪切
模式空间: 存放当前处理的行,将结果输出;若当前行不符合处理条件,则原样输出;处理完当前行再读入下一行来处理。
保持空间: 作用类似于 “剪贴板”; 默认存放一个空行(换行符\n)
基本动作
-H : 模式空间 --[追加]--> 保持空间 //复制
-h : 模式空间 --[覆盖] -->保持空间 //复制
-G : 保持空间--[追加]--> 模式空间 //粘贴
-g : 保存空间--[覆盖] -->模式空间 //粘贴
例子:
sed '1,3H;$G' reg.txt //把第1-3行复制到文件末尾
sed '1h;2,3H;$G' reg.txt //可避免出现空行
sed '1h;1d;$G' reg.txt //把第1行剪切到文件末尾
sed '1h;2H;1,2d;$G' reg.txt //把第1-2行剪切到文件末尾
sed 流程控制
! 取反操作; 根据定址条件取反
sed -n '/bash$/!p' /etc/passwd
n 读下一行 ; 产生隔行/跳行的效果
sed -n 'p;n' reg.txt //输出奇数行
sed -n 'n;p' reg.txt //输出偶数行
awk工具概述
awk编程语言/数据处理引擎
创造者: Aho, Weinberger, kernighan
基于模式匹配检查输入文本,逐行处理并输出;通常用在shell脚本中,获取指定数据;单独用时,可对文本数据做统计。
用法:
格式1 : 前置命令 | awk [选项] '[条件]{编辑指令}' //多条语句可以分号分隔; print 是最常用的指令
格式2: awk [选项] ' [条件]{编辑指令}' 文件.. .. //注意:awk条件和指令需要使用单引号
常用命令选项
-F : 指定分隔符,可省略(默认空格或Tab位)
-f : 调用awk脚本进行处理
-v : 调用外部Shell变量
awk内置变量
有特殊含义,可直接使用
变量 | 用途 |
FS | 保存或设置字段分隔符,例如 FS=":" |
$n | 指定分隔的第n个字段,例如$1,$3分别表示第1,3列 |
$0 | 当前读入的整行文本内容 |
NF | 记录当前处理行的字段个数(列数) |
NR | 记录当前已读行的数量(行数) |
FNR | 保存当前行在原文本中的序号(行号) |
FILENAME | 当前处理的文件名 |
ENVIRON | 调用Shell环境变量,格式:ENVIRON["变量名"] |
# awk '{print "第"FNR"行","有"NF"列"}' m.txt
#awk '{print "Last:"$NF}' m.txt //输出每行最后一个字段
#awk -F: '$1==ENVIRON["USER"]{print $3}' /etc/passwd //输出当前用户的UID信息
awk过滤的时机?
BEGIN{} 在所有行前处理, BEGIN{}
读入第一行文本之前执行
一般用来初始化操作
{} 逐行处理
逐行读入文本执行相应的处理
是最常见的编辑指令块
END{} 在所有行后处理
在处理完最后一行文本之后执行
一般用来输出处理结果
#awk 'BEGIN {a=34;print a+12}' //预处理不需要数据文件
#awk 'BEGIN{x=0}/\ #awk 'BEGIN {print NR}END{print NR}' m.txt //预处理时,行数为0 //全部处理完以后,行数为已读入文本的行数 处理条件 格式: awk [选项] '[条件]{编辑指令}' 文件.. .. 条件的表现形式? 正则表达式 数值/字符串比较 逻辑比较 运算符 正则表达式: /正则表达式/ ~匹配 !~ 不匹配 #awk -F: '/^ro/{print}' /etc/passwd //列出以ro开头的用户记录 #awk -F: '$7!~/bash$/{print $1,$7}' /etc/passwd //列出第7个字段不以bash结尾的用户名,登录shell 数值比较 == 等于 != 不等于 > 大于 >= 大于或等于 < 小于 <= 小于或等于 #awk 'NR==2{print}' reg.txt //输出第2行文本 #awk '$2!="XX"{print}' reg.txt //输出第2列不是XX的行 #awk 'NF>=2{print}' reg.txt //输出包含2个及以上字段的行 逻辑比较测试 && 逻辑与 : 期望多个条件都成立 || 逻辑或 : 只要有一个条件成立即满足要求 #awk -F: '$3==1 || $3==7{print $1,$3}' /etc/passwd //列出UID为1或7的用户信息 运算符 + - * / % ++ -- += -= *= /= # seq 200 | awk 'BEGIN{i=0}($0%3==0)&&($0%13==0){i++}END{print i}' //计算同时被3和13整除的整数个数 awk高级应用 awk流程控制; awk数组; awk案例分析 流程控制-分支结构 单分支: if(条件){编辑指令} 双分支: if(条件){编辑指令1}else{编辑指令2} 多分支: if(条件){编辑指令1}else if(条件){编辑指令2} .. .. else{编辑指令N} #awk -F: 'BEGIN{i=0;j=0}{if($3<=500){i++}else{j++}}END{print i,j}' /etc/passwd //统计UID小于或等于500的用户个数;统计UID大于500的用户个数。 流程控制- 循环结构 while循环 while(条件){编辑指令} do while循环 do{编辑指令}while(条件) #awk -F [:/] '{i=1}{while(i<=NF){if($i~/root/){j++};i++}}END{print j}' /etc/passwd //统计/etc/passwd文件内“root”出现的次数 for循环 for(初值;条件;步长){编辑指令} 其他控制语句- 常用的中断,退出等awk指令 数组的定义及使用 定义数组: 格式: 数组名[下标]=元素值 调用: 数组名[下标] 遍历数组: 用法: for(变量 in 数组名){print 数组名[变量]} #awk -F: '!a[$7]++{print $7}' /etc/passwd 命令sort : -n //按数字升序排列 -k //针对指定的字段进行排序 -r //反向排序 # /var/access_log | sort -nr -k2
关键字
含义
break
结束当前的循环体
continue
中止本次循环,转入下一次循环
next
跳过当前行,读入下一行文本开始处理
exit
结束文本读入,转入END{}执行 如果没有END{}则直接退出awk处理操作