shell基础
1、变量的类型
- 字符串,a="xx"
- 数字,i=123
- 布尔,a=true,b=false
- 预定义变量:echo $PWD,echo$PATH,echo$USER,echo$HOME
- 数组变量:array=(1 2 3 4)
2、变量的使用
-
基本使用方法
- echo $a
- echo $
- echo "$a"
- echo $?,输出上一条命名执行情况,0为正确,1为错误。
- 注意:使用$var或${var}来访问变量,后者更为严谨。
-
数组变量使用
- array=( ` ls `)
- echo ${array[2]},输出数组中的第三个元素的值
- echo ${array},默认输出数组中的第一个元素的值
- echo ${array[*]},默认输出数组中的全部元素的值
- echo ${array[@]},默认输出数组中的全部元素的值
[root@localhost ~]# echo ${array1[@]} 123 456 789 333 #从数组下标1开始,访问2个元素 [root@localhost ~]# echo ${array1[@]:1:2} 456 789 #从数组下标1开始,访问后面的元素 [root@localhost ~]# echo ${array1[@]:1} 456 789 333- echo ${#array[*]},默认输出数组中元素的个数
[root@localhost ~]# array1[0]=123 [root@localhost ~]# array1[1]=456 [root@localhost ~]# array1[2]=789 [root@localhost ~]# echo ${array1[@]} 123 456 789 #打印数组下标 [root@localhost ~]# echo ${!array1[@]} 0 1 2- 关联数组
#声明关联数组 [root@localhost ~]# declare -A array2 #赋值 [root@localhost ~]# array2[name]=xyz [root@localhost ~]# array2[age]=18 [root@localhost ~]# array2[home]=chengdu #输出数组 [root@localhost ~]# echo ${array2[@]} xyz 18 chengdu #通过关键字访问数组值 [root@localhost ~]# echo ${array2[age]} 18 [root@localhost ~]# echo ${array2[name]} xyz #访问所有索引 [root@localhost ~]# echo ${!array2[@]} name age home #统计数组元素个数 [root@localhost ~]# echo ${#array2[@]} 3 [root@localhost ~]#- 数组统计使用
有一个文件sex,其中f代表女性,m代表男性,统计男女个数
aaa f bbb m ccc f ddd m aa m dd f cc f#!/usr/bin/bash #声明一个关联数组 declare -A sex_account #读取每一行 while read line do #获取每一行中的第二列数 tag=$(echo $line | awk '{print $2}') let sex_account[$tag]++ done</root/sex for i in ${!sex_account[@]} do echo "索引名称是:$i;索引值个数为:${sex_account[$i]}" done结果:
[root@localhost ~]# chmod +x sex_statistics [root@localhost ~]# ./sex_statistics 索引名称是:f;索引值个数为:4 索引名称是:m;索引值个数为:3 -
数字型变量使用
- 整数计算
[root@localhost ~]# a=1;echo $a;echo $((a+1)) 1 2 [root@localhost ~]# echo $a;echo $((a=a+1));echo $a 1 2 2 [root@localhost ~]# echo $((10+2)) 12 [root@localhost ~]# echo $((10*2)) 20 [root@localhost ~]# echo $((10/2)) 5 [root@localhost ~]# echo $((3%5)) 3 #中括号要更方便简单些 [root@localhost ~]# echo $[1+2] 3 [root@localhost ~]# echo $[10-2] 8 [root@localhost ~]# echo $[10/2] 5 [root@localhost ~]# echo $[3/5] 0 [root@localhost ~]# echo $[3%5] 3 [root@localhost ~]# echo $[(1+2)*5] 15- 浮点数计算
[root@localhost ~]# awk 'BEGIN{print 1/3}' 0.333333 [root@localhost ~]# awk 'BEGIN{printf("%.2f\n",1/3)}' 0.3- 字符串操作
[root@localhost ~]# name="hello world" #取值操作 [root@localhost ~]# echo ${name:1:3} ell #取长度操作 [root@localhost ~]# echo ${#name} 11 #掐去头部的hello [root@localhost ~]# echo ${name#hello} world #掐去尾部的world [root@localhost ~]# echo ${name%world} hello #把hello替换为nihao [root@localhost ~]# echo ${name/hello/nihao} nihao world #匹配第一个ll并把之前的去掉 [root@localhost ~]# echo ${name#*ll} o world #从左向右匹配第一个o并把之前的去掉 [root@localhost ~]# echo ${name#*o} world #从左向右匹配最后一个o并把之前的去掉,*在左就是左开始匹配,*在右就从右开始匹配 [root@localhost ~]# echo ${name##*o} rld #从右向左匹配第一个o并把尾去掉 [root@localhost ~]# echo ${name%o*} hello w #从右向左匹配最后一个o并把尾去掉 [root@localhost ~]# echo ${name%%o*} hell [root@localhost ~]# echo $url www.baidu.com [root@localhost ~]# echo ${url#*.} baidu.com [root@localhost ~]# echo ${url%.*} www.baidu- 布尔
[root@localhost ~]# a=1;b=2 [root@localhost ~]# ((a<b)) [root@localhost ~]# echo $? 0 [root@localhost ~]# ((a>b)) [root@localhost ~]# echo $? 1 #0表示正确,1表示错误 -
算术判断
注意,这是整数比对,若是字符串比对需要用=或者==
#等于,注意中括号两边都要有空格
[root@localhost ~]# [ 2 -eq 2 ];echo $?
0
#不等于
[root@localhost ~]# [ 2 -ne 3 ];echo $?
0
#大于
[root@localhost ~]# [ 3 -gt 2 ];echo $?
0
#大于等于
[root@localhost ~]# [ 3 -ge 3 ];echo $?
0
#小于
[root@localhost ~]# [ 3 -lt 4 ];echo $?
0
#小于等于
[root@localhost ~]# [ 3 -le 4 ];echo $?
0
示列:发现磁盘空间使用率大于85%时,邮件报警
#!/usr/bin/bash
Disk_Free=$(df -h | grep "/$" | awk '{ print $5 }' | awk -F "%" '{print $1}')
if [ $Disk_Free -ge 85 ];then
echo "current disk have usage :$Disk_Free"%
fi
示列:发现内存空间使用率大于85%时,邮件报警
#!/usr/bin/bash
Mem_total=$(free -m | grep 'Mem' | awk '{print $2}')
Mem_used=$(free -m | grep 'Mem' | awk '{print $3}')
Mem_percent=$(($Mem_used*100/$Mem_total))
if [ $Mem_percent -ge 85 ];then
echo "memery have used :"${Mem_percent}%
fi
- 字符串比较
#等于
[root@localhost ~]# [ "aaa" = "aaa" ];echo $?
0
#不等于
[root@localhost ~]# [ "aaa" != "bbb" ];echo $?
0
#不为空时为真
[root@localhost ~]# [ -n "aaa" ];echo $?
0
#为空时为真
[root@localhost ~]# [ -z "aaa" ];echo $?
1
[root@localhost ~]# [ -z "" ];echo $?
0
#字符串中有多个a时为真
[root@localhost ~]# [[ "aaa" == a* ]];echo $?
0
#字符串比较
[root@localhost ~]# echo $a
hello
#字符串长度为0
[root@localhost ~]# [ -z $a ];echo $?
1
#字符串长度不为0
[root@localhost ~]# [ -n $a ];echo $?
0
- 正则比对
[root@localhost ~]# num=123123
[root@localhost ~]# [[ ${num} =~ ^[0-9]+$ ]];echo $?
0
[root@localhost ~]# [[ "$num" =~ ^[0-9]+$ ]];echo $?
0
- 逻辑判断
#与运算,也就and
[root@localhost ~]# [ 2 -ge 1 -a 3 -lt 4 ];echo $?
0
#或运算,也就是or
[root@localhost ~]# [ 2 -ge 1 -o 3 -gt 4 ];echo $?
0
#与运算,也就and
[root@localhost ~]# [[ 2 -ge 1 && 3 -gt 4 ]];echo $?
1
#或运算,也就是or
[root@localhost ~]# [[ 2 -ge 1 || 3 -gt 4 ]];echo $?
0
[root@localhost ~]# [ 2 -gt 1 ];echo $?
0
#非运算,也就是not,用感叹号表示!
[root@localhost ~]# [ ! 2 -gt 1 ];echo $?
1
注意:[[]]是[]的扩展语法,在老sh里并不支持,推荐[]
- 内置判断
-e file如果文件存在,则为真
-d file如何文件为子目录,则为真r
-f file如何文件为一个普通文件,则为真
-r file如何文件可读,则为真
-s file如何文件长度不为0,则为真
-w file如何文件可写,则为真
-x file如何文件可执行,则为真
- 变量赋值
[root@localhost ~]# url="www.tencent.com"
[root@localhost ~]# echo $url
www.tencent.com
[root@localhost ~]# echo ${url-www.alibaba.com}
www.tencent.com
[root@localhost ~]# unset url
[root@localhost ~]# echo $url
#相当于给url设定了默认值
[root@localhost ~]# echo ${url-www.alibaba.com}
www.alibaba.com
[root@localhost ~]#
- 变量替代
[root@localhost ~]# url="www.xiaomi.com"
[root@localhost ~]# echo $url
www.xiaomi.com
[root@localhost ~]# echo ${url:-www.baidu.com}
www.xiaomi.com
[root@localhost ~]# unset url
[root@localhost ~]# echo ${url:-www.baidu.com}
www.baidu.com
3、文件描述符
- 输入文件,标准输入为0
- 输出文件,标准输出为1
- 错误输出文件,标准错误2
4、特殊符号的使用
- 双引号用于括起一段字符串值,支持$var形式的变量替换
[root@localhost ~]# name="this is string"
[root@localhost ~]# echo $name
this is string
-
单引号也表示其内容是字符串值,不支持转义
-
\反斜杠某些时候表示的转义
[root@localhost ~]# echo "aaabbb"
aaabbb
[root@localhost ~]# echo -e "aaa\nbbb"
aaa
bbb
- ((a=a+1))是整数的扩展。把里面的变量当作整数去处理。
- $(())对变量进程操作。
[root@localhost ~]# a=1
[root@localhost ~]# b=2
[root@localhost ~]# echo $((a+b))
3
[root@localhost ~]# echo $(a+b)
-bash: a+b: 未找到命令
- ({1..10})等价于seq 1 10,表示从1到10。
[root@localhost ~]# a=({1..10})
[root@localhost ~]# echo ${a[@]}
1 2 3 4 5 6 7 8 9 10
[root@localhost ~]# echo ${a[*]}
1 2 3 4 5 6 7 8 9 10
- seq 1 3 10 表示生成一个1到10,步进为3。
[root@localhost ~]# a= seq 1 10
1
2
3
4
5
6
7
8
9
10
[root@localhost ~]# a= seq 1 2 10
1
3
5
7
9
- $(ls)表示执行ls后的结果。与``类似。不过可以嵌套。
[root@localhost ~]# ls
1.sh anaconda-ks.cfg demo lnmp-install.log test1.txt test2.txt test.log
2.sh cmdline hello.sh test test1.txt.bak test2.txt.bak xyz
[root@localhost ~]# echo $(ls)
1.sh 2.sh anaconda-ks.cfg cmdline demo hello.sh lnmp-install.log test test1.txt test1.txt.bak test2.txt test2.txt.bak test.log xyz
- `反引号。用法比较特殊,代表命名的输出。
[root@localhost ~]# echo my dir is `ls`
my dir is 1.sh 2.sh anaconda-ks.cfg cmdline demo hello.sh lnmp-install.log test test1.txt test1.txt.bak test2.txt test2.txt.bak test.log xyz
5、&&与||的用法
简单的逻辑可以使用&&和||去替代,&为真时就执行后续的代码,||为假时就执行后续的代码。
[ -e 3.sh ] && echo exist || echo not exist
表示3.sh文件存在时就输出exist,不存在时就输出not exist。可以代替简单的if...else...逻辑。
6、if逻辑结果
if [ condition ] ; then...;fi
if [ condition ] ; then...;else...;fi
if [ condition ] ; then...;elif...;fi
[root@localhost ~]# if [ -e xyz ];then echo "exist";else echo "not exist";fi
exist
[root@localhost ~]# if [ -e 111 ];then echo "exist";else echo "not exist";fi
not exist
[root@localhost ~]# [ -e xyz ] && echo "exist" || echo "not exist"
exist
[root@localhost ~]# [ -e 111 ] && echo "exist" || echo "not exist"
not exist
7、for循环语句
for((a,b,c));do...;done
[root@localhost ~]# for ((i=0;i<10;i++));do echo $i;done
0
1
2
3
4
5
6
7
8
9
[root@localhost ~]# array=(1 2 3 4 5)
#数组的长度
[root@localhost ~]# for((i=0;i<${#array[@]};i++));do echo $i;done
0
1
2
3
4
#for的遍历循环
[root@localhost ~]# for i in ${array[@]};do echo $i;done
1
2
3
4
5
[root@localhost ~]# for i in $(seq 1 10);do echo $i;done
1
2
3
4
5
6
7
8
9
10
#注意ls是被反引号括起来,反引号在esc按键下方
[root@localhost ~]# for i in `ls`;do echo $i;done
1.sh
2.sh
anaconda-ks.cfg
cmdline
demo
8、while循环语句
while 判断语句
do
执行语句
done
9、退出控制
- return函数返回
- exit脚本进程退出
- break退出当前循环
- continue跳过当前的循环
10、shell运行环境
- ()表示在子shell中运行 ,也就是在子进程中运行。
- {}表示在shell中执行
- $$当前脚本执行的pid
- &后台执行
- &!运行在后台的最后一个作业的PID(进程ID)
11、程序前后台切换
- 在命令末尾加上 & 符号,就可以让程序在后台运行
[root@localhost ~]# sleep 100&
[2] 9743
- 如果程序正在前台运行,可以使用 Ctrl+z 选项把程序暂停
[root@localhost ~]# sleep 100
^Z[1] 完成 sleep 110
[3]+ 已停止 sleep 100
- bg %[number] 命令把这个程序放到后台运行
[root@localhost ~]# jobs
[2]- 完成 sleep 100
[3]+ 已停止 sleep 100
[root@localhost ~]# bg 3
[3]+ sleep 100 &
数字为3的进程已经停止,此时可以用bg 3将其调用到后台继续运行
- 对于所有运行的程序,可以用jobs –l 指令查看
[root@localhost ~]# jobs -l
[3]+ 9744 完成 sleep 100
- 也可以用 fg %[number] 指令把一个程序掉到前台
[root@localhost ~]# jobs -l
[1]+ 9745 停止 sleep 100
[root@localhost ~]# bg 1
[1]+ sleep 100 &
[root@localhost ~]# fg 1
sleep 100
- kill终止后台运行的程序
[root@localhost ~]# jobs
[1]+ 已停止 sleep 100
[root@localhost ~]# kill %1
[1]+ 已停止 sleep 100
[root@localhost ~]# jobs
[1]+ 已终止 sleep 100
12、shell输入输出重定向
- “>”表示将结果输出至某个文件,若文件中有内容,那么内容将会被覆盖,示例如下:
[root@localhost ~]# cat test
hello to testerhome
hello form testerhome
[root@localhost ~]# echo "ni hao" > test
[root@localhost ~]# cat test
ni hao
- “>>”表示将结果追加至某个文件,若文件中有内容,结果将追加至内容之后,不会覆盖原来的文件内容,示例如下:
[root@localhost ~]# cat test
ni hao
hello world
[root@localhost ~]# echo "this is a test" >> test
[root@localhost ~]# cat test
ni hao
hello world
this is a test
-
"2>"表示将错误信息输入至某个文件。
-
"&>"表示不管正确与否都将信息输入至某个文件。
-
|表示管道,也就是前一个命名的输出传入下一个命名的输入
-
< file输入重定向
-
1>&2 意思是把标准输出重定向到标准错误.
2>&1 意思是把标准错误输出重定向到标准输出。
&>filename 意思是把标准输出和标准错误输出都重定向到文件filename中
13、三剑客之grep
定义:数据查找定位,基于正则表达式查找满足条件的行
- 忽略大小写进行定位查找
grep -i pattern file
- 把每个匹配到的内容独立的行显示,只显示匹配到的内容
grep -o pattern file
- 不显示匹配的行
grep -v pattern file
- 使用扩展正则表达式
grep -E pattern file
- 递归搜索
grep pattern file -r dir
- 打印命中数据的上下文
grep -A -B -C pattern file
14、三剑客之awk
定义:数据切片,根据定位到的数据行处理其中的分段,与python中的元素分割类似
- 开始和结束
awk 'BEGIN{}END{}'
- 正则匹配
awk '/Running/'
- 区间选择
awk '/aa/,/bb/'
示例:取15至19区间的数字
[root@localhost ~]# seq 20 | awk '/15/,/19/'
15
16
17
18
19
- -F字段匹配
[root@localhost ~]# echo "123|456|789" | awk -F '|' '{print $2}'
456
[root@localhost ~]# echo "123|456|789" | awk -F '|' '{print $1}'
123
[root@localhost ~]# echo "123|456|789" | awk -F '|' '{print $0}'
123|456|789
[root@localhost ~]# echo "123_456+789" | awk -F '+|_' '{print $0}'
123_456+789
[root@localhost ~]# echo "123_456+789" | awk -F '+|_' '{print $1}'
123
[root@localhost ~]# echo "123_456+789" | awk -F '+|_' '{print $2}'
456
[root@localhost ~]# echo "123_456+789" | awk -F '+|_' '{print $3}'
789
#最后登录的4个用户
[root@localhost ~]# last -n 4
root pts/2 192.168.158.1 Wed Dec 11 13:53 still logged in
root pts/1 192.168.158.1 Wed Dec 11 12:40 - 15:53 (03:12)
root pts/0 192.168.158.1 Wed Dec 11 09:01 - 14:40 (05:39)
root pts/0 192.168.158.1 Tue Dec 10 09:31 - 14:37 (05:06)
[root@localhost ~]# last -n 4 | awk '{print $3}'
192.168.158.1
192.168.158.1
192.168.158.1
192.168.158.1
#i++可以显示行号,方便查询
[root@localhost ~]# awk -F "'" '/^menu/{print $2}' /boot/grub2/grub.cfg
CentOS Linux (3.10.0-1062.9.1.el7.x86_64) 7 (Core)
CentOS Linux (3.10.0-957.el7.x86_64) 7 (Core)
CentOS Linux (0-rescue-27ff2a8edea7471692d8fb69998db98d) 7 (Core)
[root@localhost ~]# awk -F "'" '/^menu/{print i++,$2}' /boot/grub2/grub.cfg
0 CentOS Linux (3.10.0-1062.9.1.el7.x86_64) 7 (Core)
1 CentOS Linux (3.10.0-957.el7.x86_64) 7 (Core)
2 CentOS Linux (0-rescue-27ff2a8edea7471692d8fb69998db98d) 7 (Core)
[root@localhost ~]#
- 字段匹配
awk '$2~/xxx/'
- 取第二行
awk 'NR==2'
示例:取第二行的数据
[root@localhost ~]# seq 20 | awk 'NR==2'
2
- 去掉第一行
awk 'NR>1'
示例:去掉标题行
[root@localhost ~]# vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 482620 23508 330220 0 0 1 0 23 42 0 0 100 0 0
[root@localhost ~]# vmstat | awk 'NR>1'
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 482396 23508 330220 0 0 1 0 23 42 0 0 100 0 0
- RS记录分割符,或者是行分隔符
[root@localhost ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/xyz
[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}{print $0}'
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/root/bin
[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}{print $1}' | awk -F "/" '{print $1, $2 $3 $4}'
usrlocalsbin
usrlocalbin
usrsbin
usrbin
rootbin
rootxyz
[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}{print $1}' | awk -F "/" '{print $1,$2,$3,$4}'
usr local sbin
usr local bin
usr sbin
usr bin
root bin
root xyz
将PATH变量用“:”进行分割。
- FS字段分隔符
[root@localhost ~]# echo '1|2#3_4'
1|2#3_4
[root@localhost ~]# echo '1|2#3_4' | awk 'BEGIN{FS="#|_|\\|"}{print $0}'
1|2#3_4
[root@localhost ~]# echo '1|2#3_4' | awk 'BEGIN{FS="#|_|\\|"}{print $1}'
1
[root@localhost ~]# echo '1|2#3_4' | awk 'BEGIN{FS="#|_|\\|"}{print $2}'
2
[root@localhost ~]# echo '1|2#3_4' | awk 'BEGIN{FS="#|_|\\|"}{print $3}'
3
[root@localhost ~]# echo '1|2#3_4' | awk 'BEGIN{FS="#|_|\\|"}{print $4}'
4
用#|_符号分割'1|2#3_4'字符串
- OFS输出数据的字段分隔符
[root@localhost ~]# echo '1|2#3_4' | awk 'BEGIN{FS="#|_|\\|"}{print $1,$2,$3,$4}'
1 2 3 4
[root@localhost ~]# echo '1|2#3_4' | awk 'BEGIN{FS="#|_|\\|";OFS="_"}{print $1,$2,$3,$4}'
1_2_3_4
OFS输出数据默认是空格进行分割,OFS可以指定分割的符号,比如上例中的下划线“_”符号进行分割。
- ORS输出字段的行分隔符
[root@localhost ~]# echo '1|2#3_4' | awk 'BEGIN{RS="#|_|\\|"}{print $1}'
1
2
3
4
[root@localhost ~]# echo '1|2#3_4' | awk 'BEGIN{RS="#|_|\\|";ORS=":"}{print $1}'
1:2:3:4:[root@localhost ~]#
[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}{print $0}'
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/root/bin
/root/xyz
[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}{print $0}' | awk 'BEGIN{FS="\n";ORS=":"}{print $0}'
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/xyz::[root@localhost ~]#
ORS输出字段的行分隔符默认是换行符“\n”,上例中改变分隔符为":"冒号时,可以将输出字段拼接成一行。
- NR记录数
[root@localhost ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/xyz
[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}{print NR,$0}'
1 /usr/local/sbin
2 /usr/local/bin
3 /usr/sbin
4 /usr/bin
5 /root/bin
6 /root/xyz
#加END后,统计总的行数
[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}END{print NR}'
6
[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}{print NR}'
1
2
3
4
5
6
[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}{print NR,$0}'
1 /usr/local/sbin
2 /usr/local/bin
3 /usr/sbin
4 /usr/bin
5 /root/bin
6 /root/xyz
#输出最后一行
[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}END{print NR,$0}'
6 /root/xyz
- 数字的计算
比如:请利用bash自动输出2、5、8,并求和
1|2|3
4|5|6
7|8|9
echo -e "1|2|3\n4|5|6\n7|8|9" | awk -F '|' 'BEGIN{a=0}{a=a+$2;print $2}END{print a}'
结果:
2
5
8
15
比如:乘除法计算
[root@localhost ~]# awk 'BEGIN{print 1/3}'
0.333333
[root@localhost ~]# awk 'BEGIN{printf "%.2f\n",1/3}'
0.33
[root@localhost ~]# awk 'BEGIN{printf "%.3f\n",1/3}'
0.333
[root@localhost ~]# awk 'BEGIN{printf "%.4f\n",1/3}'
0.3333
[root@localhost ~]# awk 'BEGIN{printf "%.4f",1/3}'
0.3333[root@localhost ~]#
比如:计算前数据之和
[root@localhost ~]# seq 10 2 20
10
12
14
16
18
20
[root@localhost ~]# seq 10 2 20 | awk '{sum+=$1}{print sum}'
10
22
36
52
70
90
比如:求平均值
[root@localhost ~]# seq 10 2 20 | awk '{sum+=$1}{print sum/NR}'
10
11
12
13
14
15
15、三剑客之sed
定义:数据修改,根据定位到的数据行修改数据
- 命令使用
sed 's/正则/结果/g'
正则:需要替换的内容
结果:替换成什么
g:替换所有
- 修改替换数据
例如:将test2.txt中的haha替换为hello
命令:
[root@localhost ~]# sed -i 's/haha/hello/' test2.txt
示例:
[root@localhost ~]# cat test2.txt
haha world
haha from testerhome
HELLO TO TESTERHOME
hha
huhu
[root@localhost ~]# sed -i 's/haha/hello/' test2.txt
[root@localhost ~]# cat test2.txt
hello world
hello from testerhome
HELLO TO TESTERHOME
hha
huhu
示列:返回一个 IP 数组,并且按 IP 最后一位排序返回。
str='192.169.32.1?!289.0.0.3!192.168.0.11?192.163.10.18?!192.168.5.4'
解答:
#方法一:-n代表升序排列,-r代表降序排列
[root@localhost ~]# array=`echo $a | sed 's/[?!]/\n/g'|sort -t "." -k 4 -n`
[root@localhost ~]# echo ${array[@]}
192.169.32.1 289.0.0.3 192.168.5.4 192.168.0.11 192.163.10.18
#方法二
[root@localhost ~]# array=`echo $str | awk -F '!|?|?!' '{print $1"\n"$2"\n"$3"\n"$4"\n"$5 }'|sort -n -t . -k 4`
[root@localhost ~]# echo $array
192.169.32.1 289.0.0.3 192.168.5.4 192.168.0.11 192.163.10.18
#方法三
[root@localhost ~]# echo $str
192.169.32.1?!289.0.0.3!192.168.0.11?192.163.10.18?!192.168.5.4
[root@localhost ~]# echo $str | awk '{split($0,a,"!|?");for (i in a) {print i,a[i]}}'
4 192.168.0.11
5 192.163.10.18
6
7 192.168.5.4
1 192.169.32.1
2
3 289.0.0.3
[root@localhost ~]# echo $str | awk '{split($0,a,"!|?");for (i in a) {print i,a[i]}}'|sort -nk 4 -t .
2
6
1 192.169.32.1
3 289.0.0.3
7 192.168.5.4
4 192.168.0.11
5 192.163.10.18
[root@localhost ~]# array=`echo $str | awk '{split($0,a,"!|?");for (i in a) {print a[i]}}'|sort -nk 4 -t .`
[root@localhost ~]# echo $array
192.169.32.1 289.0.0.3 192.168.5.4 192.168.0.11 192.163.10.18
- 替换数据时备份,防止替换文件时出错。
命令:
[root@localhost ~]# sed -i.bak 's/haha/hello/' test2.txt
示例:在修改文件后,会自动生成一个.bak的备份文件,注意(.bak)并非标准格式,可以根据需要随意设置备份文件格式。
[root@localhost ~]# cat test2.txt
haha world
hha
huhu
[root@localhost ~]# sed -i.bak 's/haha/hello/' test2.txt
[root@localhost ~]# cat test2.txt
hello world
hha
huhu
[root@localhost ~]# cat test2.txt.bak
haha world
hha
huhu
- 打印第几行
比如:打印第5行数据
sed -n '5p'
[root@localhost ~]# seq 1 10
1
2
3
4
5
6
7
8
9
10
[root@localhost ~]# seq 1 10 | sed -n '5p'
5
比如:打印5到9的数据
[root@localhost ~]# seq 1 10 | sed -n '5,9p'
5
6
7
8
9
- 删除数据
比如:删除第二行数据
sed '2d'
[root@localhost ~]# seq 1 10 | sed '2d'
1
3
4
5
6
7
8
9
10
- 取数据高级技巧
\1\2匹配的字段
比如:获取123至134的最后一位数,和后面两位数。比如123就获取3,再获取23。
[root@localhost ~]# seq 123 134
123
124
125
126
127
128
129
130
131
132
133
134
#匹配第三为数字,用括号括起来即表示要匹配的位置
[root@localhost ~]# seq 123 134 | sed -E 's/..(.)/\1/g'
3
4
5
6
7
8
9
0
1
2
3
4
#匹配第二位和第三位数字
[root@localhost ~]# seq 123 134 | sed -E 's/.(.)(.)/\1\2/g'
23
24
25
26
27
28
29
30
31
32
33
34
16、文件判断
[ -e dir|file ]
[ -d dir ] 是否存在,⽽而且是⽬目录
[ -f file ] 是否存在,⽽而且是⽂文件
[ -r file ] 读权限
[ -x file ] 执⾏行行权限
[ -w file ] 写权限
常见使用场景是备份数据库
#!/usr/bin/bash
#定义备份目录站点
back_dir=/var/mysql_back
# test -d $back_dir || mkdir -p $back_dir
if [ ! -d $back_dir ];then
mkdir -p $back_dir
fi
echo "开始备份..."
17、执行shell
- ./XXX.sh方式执行shell,注意其是在子进程中执行
- bash XXX.sh方式执行shell,其也是在子进程中执行
- source XXX.sh方式执行shell,注意其是在当前进程中执行
- . XXX.sh方式执行shell,其是在当前进程中执行
示例:1.sh
#!/bin/bash
echo $demo_var
#当前进程中定义一个变量
[root@localhost ~]# demo_var="hello shell"
[root@localhost ~]# echo $demo_var
hello shell
[root@localhost ~]# vi 1.sh
[root@localhost ~]# chmod u+x 1.sh
#第一种方式执行时无法获取当前进程中的变量值
[root@localhost ~]# ./1.sh
[root@localhost ~]# bash 1.sh
#source方式执行脚本时可以获取当前进程中的值
[root@localhost ~]# source 1.sh
hello shell
[root@localhost ~]# . 1.sh
hello shell
[root@localhost ~]#
#若要子进程中也能获取变量,需要用export将其导出
[root@localhost ~]# export demo_var
[root@localhost ~]# ./1.sh
hello shell
[root@localhost ~]# bash 1.sh
hello shell
[root@localhost ~]# source 1.sh
hello shell
[root@localhost ~]# . 1.sh
hello shell
#删除环境变量
[root@localhost ~]# unset demo_var
[root@localhost ~]# ./1.sh
[root@localhost ~]#
18、位置变量
注意第10个位置参数的写法
#!/bin/bash
#位置参数$1,$2...$9,${10}
para1=$1
#这样设置后,当第二个位置参数为空时将会打印出-,方便识别
para2=${2-_}
echo $para1
echo $para2
[root@localhost ~]# vi 2.sh
[root@localhost ~]#
[root@localhost ~]# chmod u+x 2.sh
[root@localhost ~]# bash 2.sh -a -b
-a
-b
[root@localhost ~]# bash 2.sh -a
-a
[root@localhost ~]# vi 2.sh
[root@localhost ~]# bash 2.sh -a
-a
[root@localhost ~]# bash 2.sh -a -b
-a
-b
[root@localhost ~]# vi 2.sh
[root@localhost ~]# bash 2.sh -a -b
-a
-b
#当参数设置为para2=${2-_},第二个位置参数为空时,就能识别,否则为空不容易发现
[root@localhost ~]# bash 2.sh -a
-a
_
[root@localhost ~]#
19、Shell输入输出
read (选项)(参数):从控制台读取数据
-p:指定读取值时的提示符
-t:指定读值的等待时间【单位:秒】,超时不等待
参数:指定读取值的变量名
#!/bin/bash
read -p "input a number:" NUM1
echo "num1=$NUM1"
read -t 5 -p "在5秒内,输入一个数num=" NUM2
echo "num=$NUM2"
20、Linux定时任务调度
crond任务调度
系统在某个时间段执行特定的命令或程序。
1、数据库的定时备份操作。
2、系统一些重复工作,病毒扫描等。
用法
crontab 【选项】
-e:编辑crontab定时任务
-l:查询crontab任务
-f:删除当前用户所有的crontab任务
-r:终止任务调度
service crond restart:重启任务调度
crontab -e
*/1 * * * * ls -l /etc > /tmp/to.txt -- 每小时的每分钟执行
第一个*:一小时中的第几分钟【0-59】
第二个*:一天中的第几个小时【0-23】
第三个*:一个月当中的第几天【1-31】
第四个*:一年中的的第几月【1-12】
第五个*:一周当中对的星期几【0-7 0和7都表示 周日】
21、同时显示两个文件的差异
diff -c file1 file2
以并列的方式显示两个文件的差异
diff -y file1 file2

浙公网安备 33010602011771号