SourceURL:file:///home/student/Desktop/linux/一阶段/二阶段/shell脚本精.docx
shell脚本
基本信息
以#!开头加解释器(/bin/bash) #!/bin/bash
cat /etc/sells 查看本机的全部解释器
bash -x ****.sh 可查看该脚本为什么输出此结果
>重定向标准输出
- 重定向错误的输出
&>重定向全部输出
/dev/null 黑洞(垃圾站不占用空间)
变量
a=11
echo $a 查看变量
unset a 取消变量
export 设置全局变量 (所有bash可用变量)
预定义变量
$0 输出当前所在的进程或者脚本名字
$$ 输出当前运行进程的PID号
$? 输出命令执行之后的返回状态,0表示正常。非0表示异常
$# 输出已经加载的位置变量个数
$* 输出所有位置变量值
vim a.sh aa bb cc dd
echo $0
echo $1
echo $2
echo $3
./a.sh 运行输出 aa bb cc
定界符
双引号 “ ” : 允许使用$引用变量
单引号 ‘ ’: 禁止引用变量,都视为文本
反撇号 ` `: 将命令的输出作为变量值
read 只设置变量不赋值
vim user.sh
read -p “请输入用户名:” name
useradd $name
./user.sh 运行结果先输入用户名字给name值
stty -echo 取消显示命令行
stty echo 显示
shell加减乘除 取余、求模
整数: expr、$[] 、let
expr
直接在命令行输入 expr 1 + 1
使用乘法时 expr 1 \* 2
$[]
echo $[1+1]
let
let c=2+2 然后echo $c
let a=a+5 = let a+=5
小数
bc
交互:输出bc进入小数计算器
非交互:echo1+1.9 | bc
echo “scale=2;10/3” | bc scale=2 保留两位小数
条件判断
test
-z 判断是否为空
a=1
test -z a
echo $? 输出非零则a不为空
-n 判断是否不为空
命令判断
A && B 当A命令执行成功才执行B命令
当放入测试echo $?时两个条件必须同时对才算运行成功
A || B 当A命令执行失败才执行B命令
当放入测试echo$?时两个条件有一个对即运行成功
a=11
test -z $a && echo y || echo n 输出n
判断a是否为空为空则输出y 不为空则输出n
test !-z $a && echo y || echo n 输出n !!!!!
判断a是否不为空不为空则输出y 为空则输出n
字符串比较
== 两个字符穿是否相同
a=1 b=2
[ a == b ] && echo y || echo n 输出为n不相同
!= 两个字符串是否不同
整数值的比较
-eq 等于
-ne 不等于
-ge 大于或等于
-le 小于或等于
-gt 大于
-lt 小于
[ 3 -le 4 ] && echo y || echo n y
文件状态
-e 判断对象是否存在
-d 判断对象是否为目录
-f 判断对象是否为文件
-r 判断对象是否可读 -w写 -x 执行
[-e /etc/aaaa ] && echo y || echo n 存在输出y不存在输出n
if结构
双分支模板
if 条件
then *** 条件对则执行
else *** 否则
fi 结束
多分支
if 条件1
then **
elif 条件2
then ***
else ***
fi
循环
for循环
固定次数的循环
模板:
for 变量名 in 值
do
命令
done
案例:
for i in {1..5}
do
echo $i
done 输出1 2 3 4 5
while循环
不限定次数的循环
案例:
i=1
while [ $i -it 5 ]
do
echo hello
done
循环下加入let i++则不为死循环
终断
break 跳出当前循环直接输出循环后面的语句
continue 停止当前循环继续下一次循环
for i in {1..5}
do
[ $i -eq 3 ] && continue
echo $i
done
echo gg
当i等于3时则停止循环进入4的循环
exir 退出整个脚本
case(简短的if)
read -p “请输入一个数字:” num
case $num in
1)
echo ***
;;
2)
echo **
;;
echo **
;;
*)
echo
;;
esac
查看系统中的启动端口信息
ss
-n以数字格式显示端口号
-t显示tcp连接的端口
-u显示udp
-l显示服务正在监听的端口信息
-p显示监听端口的服务名称
ss -atunlp | grep httpd:80
function 函数
函数名 () {
命令
}
下次使用只需输入函数名字即可
字符串的处理
截取
${变量名:起始位:取几位}
A=3133928523
echo {A:0:2} 13
下图为在固定的字符串中提取随机的数
替换
${变量名/要替换的/替换为} 只替换第一位符合条件的
A=3133 133
${A//3/*} 全部替换
掐头去尾
A=root:123:321:456
从左往右 ${变量名#要删的}
${A#*:} 删到第一个冒号
123:321:456
${A##*:} 删到最后一个冒号
++++++++++++++++++++++++++
从右往左 ${变量名%要删的}
${A%:*} 删到第一个冒号 (注冒号位置)
设置变量初始值
read -p “请输入密码(默认为123)” pass
echo ${pass:-123} | passwd --stdin $name
正则表达式
工具 grep -i 不区分大小写 -v取反
^匹配开头
$匹配结尾
[]查找集合中的所有字符
. 查找任意单个字符 .一个点代表一个字符 (空格也是字符)
* 匹配前一个字符任意字符
.* 相当于通配符
拓展正则符号
单词边界例子:
athe
the
thea
egrep “\bthe” user the thea
egrep “the\b” user the athe
egrep “\bthe\b” user the = egrep “\<the\>\”
正则示例
补充
\w 可以匹配 数字 字母 下划线
\s 可以匹配 空格和tab键
\d 可匹配 数字和[0-9]等效
grep --p “\d” a.txt
\d{4} 四位
sed
非交互式的编辑器 逐行处理
格式: 前置命令 | sed [选项] 条件 指令
格式: sed ‘定位’ 文件名字
选项
-n 屏蔽默认输出
-r 支持扩展正则(默认只支持基本正侧)
-i 修改源文件 (默认不动源文件操作不会修改)
指令
输出p 删除d 替换s
补充(a往下新增一行 i往上新增一行 c替换整行)
sed ‘2a xxxxx’ a.txt 在第二行下面加一行输入xxxx
条件
行号 /字符串/
sed ‘p’ user 输出user里的内容(两份)
sed -n ‘(可加行号指定输出)p’ user (2,4p)第2行到第4行 (2p;4p)第2行和第4行 加-n只输出一份
(1~2p) 从第一行开始每隔2行输出一次 奇数行
(2~2p)偶数行
sed运用示例
sed -n ‘/^root/p’ user 输出以root开头 去除^侧输出包含root的
sed -nr ‘/^root | ^bin/p’ user -r代表后面允许扩展正则使用
sed -n ‘=’ user 输出行号
sed -n ‘root=’ user 输出包含root的行号
sed -n ‘1!p’ user 输出除了第一行的内容 !是取反
“$p” 输出最后一行
‘$=’ 输出最后一行的行号 (文件的行数)
s替换
sed ‘s/2017/6666’ shu.txt 只会替换每一行的第一个2017
sed ‘s/2017/6666/2’ shu.txt 只会替换每一行的第二个2017
sed ‘s/2017/6666/g’ shu.txt 替换所有2017为6666
sed ‘/2024/s/2017/6666’g shu.txt 替换含有2024的行的所有2017为6666
awk 数据过滤和清洗
awk(grep)平替
格式1
awk [选项] ‘[条件{指令}]’ 文件 (多条指令用;隔开)
示例: awk ‘{print $1,$3}’ 文件 输出文件的1/3列
选项
-f 指定分隔符号(默认分隔符是空格/tab键)
示例:
awp -f : ‘/111/{print $1}’ /文件
以:作为分隔符 在该文件找包含111的行输出第一列的数据
awk内置变量
FS 保存或者设置分隔符和选项-f功能一样
$n 指定分隔的第n个字段, 例如$1、$3 分别表示第一列第三列
$0 当前读入的整行文本内容
NF 记录当前处理行的字段个数(列数)
NR 记录当前处理行的字段个数(列数)
示列:
awk ‘{print NF}’ 文件 输出该文件每一行有几列
awk ‘{print $NF}’ 文件 输出该文件每一行的最后一列数据
awk ‘{print ($NF-1)}’ 文件 输出该文件每一行的倒数第二列数据
NR同上
awk -F : ‘{print “用户名:” $1, “解释器:” $7}’ /etc/passwd
格式2
awk ‘BEGIN{指令}’ 条件{指令} END{指令}
BEGIN开始时只执行一次
awk -F : 'BEGIN{print "YHM:","JSQ:"}{print $1,$7}' /etc/passwd | column -t
awk -F : ‘{print “用户名:” $1, “解释器:” $7}’ /etc/passwd
END 在循环结束时运行一次
统计有多少用户可以登录
awk ‘BEGIN{x=0} /bash/{x++} END{print “可以登录的用户:” x}
column -t 自动对齐
awk正则
awk ‘/root/{prinr}’ 文件 查找文件内包含root的行
awk -F : '$1~/^root$/{print}' 文件 查找文件中第一列是root的行
/正则/ ~ 包含 !~不包含
awk数值和字符串的比较
awk -F : '$1=="root"' 查找第一列是root的行 (!=不等于)
awk -F : '$3>1000{print}' 查找第三列大于1000的行
awk 'NR==3{print}' 输出第三行
awk 'NR==3||NR==4{print}' 输出行号为3或者4的
运算符
awk 'NR%2==0' 输出偶数行 (!=为奇数行)
awk数组
awk ‘BEGIN{a[“1”]=11;a[“2”]=22;print a[2]}’
定义a数组存如11 22 输出22
数组名[下标]=元素值
调用数组
数组名[下标]
遍历数组(输出数组所有的值)
for(变量 in 数组名){print 数组名 [变量]}
awk 'BEGIN{a[1]=1;a[2]=2;a[3]=3;for (i in a){print a[i]} }'