awk

awk:
主要是类unix系统下对文本或者数据处理的一种工具;一种编程语言。支持自己的函数还支持用户自定义的函数和正则表达式。
awk有两种模式:命令行模式 脚本模式
命令模式:
awk [options] 'commands' files
选项:
-F:自定义字段的分割符,默认的分割符是空格或者连续的空格
-v:定义变量
-f:指定awk的脚本文件
命令:
1、范围说明,正则表达式,awk的语句{语句1;语句2...}
2、awk语句需要用分号隔开
3、调用shell的变量需要用双引号引起来
字段的分割和变量:
$0 文件本身
$1~$n:代表文件用分割符分割的第1~第n列(字段)
NF:文件当前记录的字段数(列数)
$NF:文件的最后一列
$(NF-1):
FNR/NR:行号----->变量
FILENAME 文件名
RS:换行符
"...":打印字符串
\t:制表符
FS:指定分割符
print:打印
示例:
第1行:
root uid homedir shell
# awk -F: '{print "第" NR "行:" RS $1,$3,$(NF-1),$NF}' passwd1
awk -F: '{print $NF}' passwd1----->打印最后1行
awk -F: '{print $(NF-1)}' passwd1----->打印倒数第2行
awk -F: '{print $1,$3,$(NF-1),$NF}' passwd1----->打印第1,3,6,7行
awk -F: '{print $1"的UID是:"$3}' passwd1----> $1的UID是$3(eg:root的UID是1)
awk -F: '{print NF}' passwd1
【awk -F: '{print "第"NR"行":"RS,$1,$3,$(NF-1),$NF}' passwd1】
awk -F: '{print "第"NR"行:" RS,$1,$3,$(NF-1),$NF}' passwd
awk -F: '{print $0}' passwd1
awk -F: '{print FILENAME}' passwd1
计算求和:
for ((i=1;i<=5;i++));do echo $i;done|awk '{i+=$1};END{print i}‘
for ((i=1;i<=5;i++));do echo $i;done|awk '{a+=$1};END{print a}'
for ((i=1;i<=10;i+=2));do echo $i;done|awk '{a+=$1};END{print a}'
1) 范围
BEGIN{};{}
END
(1) USERNAME HOME_DIR SHELL
root /root /bin/bash
...
# awk 'BEGIN{FS=":"};{print "USERNAME\tHOME_DIR\tSEHLL" RS $1"\t",$(NF-1)"\t",$NF}' passwd1
(2) USERNAME HOME_DIR SHELL
**************************************
# awk -F: 'BEGIN{print "USERNAME\tHOME_DIR\tSEHLL" RS "**************************************"};{print $1"\t",$(NF-1)"\t",$NF}' passwd1
(3) **************BEGIN******************
USERNAME HOME_DIR SHELL
...
**************END********************
# awk -F: 'BEGIN{print "**************BEGIN******************"}RS{print "USERNAME\tHOME_DIR\tSHELL" RS,$1"\t",$(NF-1)"\t",$NF};END{print"**************END********************"}' passwd1
2)正则表达式
== 等于
!= 不等于
>
<
>=
<=
~ 匹配于
!~ 不匹配
&&
||
awk -F: '/root/{print $1}' passwd1
awk -F: '/root/{print $1,$3,$NF}' passwd1--->将有root关键字的第1,3和最后一列打印
awk -F: 'NR==1,NR==5{print $0}' passwd1---->将第1~5行打印
awk -F: '/^root/,/^halt/{print $0}' passwd1---->将以root开头到以halt开头的行打印
awk -F: '/^adm/,NR==5{print $0}' passwd1--->将以admi开头到第5行打印
awk -F: '/^root/||/^sync/{print $0}' passwd1--->将以root开头或以sync开头的行打印
awk -F: 'NR>=2 && NR<=8{print $0}' passwd1---->将第2~8行打印
awk -F: 'NR==1,NR==10{print $0}' passwd1---->将第1~10行打印
awk -F: 'NR==1 || NR==10{print $0}' passwd1---->将第1行或第10行打印
awk -F: 'NR==1 && NR==10{print $0}' passwd1---->空
课堂练习:
1、打印可以登录操作系统的用户的所有信息
*****************BEGIN********************
*****************END**********************
# awk -F: '$7~/bash/{print $0}' passwd
# awk -F: '/bash$/{print $0}' passwd
# awk -F: '$0~/bash/{print $0}' passwd
# awk -F: 'BEGIN{print "*******BEGIN******"}$0 ~ /bash/{print $0};END{print "*********END*******"}' passwd
【cat /etc/passwd|awk -F: '/\/bin\/bash/{print $0}'| awk -F: 'BEGIN{print "*****************BEGIN********************"}RS{print $0};END{print "*****************END**********************"}' passwd】
2、打印出系统中普通用户以下信息
USERNAME UID HOME_DIR SHELL
*********************************************
*********************************************
# awk -F: 'BEGIN{print "USERNAME\tUID\tHOME_DIR\tSHELL" RS "****************"};$7~/bash/{print $1"\t"$3"\t"$(NF-1)"\t"$NF};END{print "***********"}' passwd
【awk -F: 'BEGIN{print "USERNAME\tUID\tHOME_DIR\tSHELL" RS"*********************************************"}RS{print $1,$3,$6,$7};END{print "*********************************************"}'】
3、找出文件中以数字开头awk -F: '/^[0-9]/{print $0}'
# awk '$0 ~ /^[0-9]/{print $0}'
# awk '/^[0-9]/{print $0}'
4、找出文件中以任意字母开头的
awk -F: ‘/^[a-z]/print $0’
5、使用awk打印出自己的ip地址、子网掩码和广播地址
# ifconfig eth0|awk NR==2|awk -F '[ :]+' '{print $4RS$6RS$8}'
---->10.1.1.110
10.1.1.255
255.255.255.0
截取IP 地址:
# ifconfig eth0|awk 'NR==2{print $2}'|awk -F: '{print $2}'--->10.1.1.110
ifconfig|awk 'NR==2{print $0}'|awk '{print $2}'|awk -F: '{print $2}'
ifconfig|awk 'NR==2{print $0}'|awk '{print $3}'|awk -F: '{print $2}'
ifconfig|awk 'NR==2{print $0}'|awk '{print $4}'|awk -F: '{print $2}'
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
awk的循环控制:
if语句:
(1) {if(表达式) {语句1;语句2;...}}
# awk -F: '{if($3==0){print $1,"admin"}}'
# awk -F: '{if($3!=0){print $1,"not admin"}}' passwd1
(2) {if(表达式) {语句1;语句2;...}else{语句1;语句2;...}}
# awk -F: '{if ($3==0){print $1,"is administrator"}else{print $1,"is other user"}}'
统计管理员,系统用户,普通用户的个数:
# awk -F: '{if($3==0){count++}else{i++}};END{print "管理员个数:" count;print "其他用户的个数:" i}'
# awk -F: '{if($3==0){i++}else if($3>=500 && $3!=65534){j++}else{x++}}END{print "管理员的个数为:"i;print "系统用户的个数为:"x;print "普通用户的个数为:" j}'
(3) {if(表达式1){语句1;..}else if(表达式2){语句1;..}else{语句1;...}}
if [xxx];then
xxx
elif [xxx];then
xxx
else
fi
# awk -F: '{if($3==0){print $1,"是管理员"}else if($3<500 || $3==65534){print $1,"是系统用户"}else{print $1,"是普通用户"}}'
for循环:
for ((i=1;i<=5;i++));do echo $i;done
awk 'BEGIN{for(i=1;i<=5;i++) print i}'---->打印1...5
awk 'BEGIN{for(i=1;i<=10;i+=2) print i}'
awk 'BEGIN{for(i=1;i<=10;i+=2) print i}'|awk '{a+=$1};END{print a}'
# awk 'BEGIN{for(i=0;i<=50;i+=2) print i}'|awk '{sum+=$1};END{print sum}'
while循环:
# awk 'BEGIN{i=1;while(i<=5){print i;i++}}'
# awk 'BEGIN{i=0;while(i<=10){print i;i+=2}}'
# awk 'BEGIN{i=0;while(i<=10){print i;i+=2}}'|awk '{sum+=$1}END{print sum}'
break:条件满足时中断循环
continue:条件满足时跳过循环
# awk 'BEGIN{i=0;while(i<=4){i++;if(i==3) continue;print i}}'
1
2
4
5
# awk 'BEGIN{i=0;while(i<=4){i++;if(i==3) break;print i}}'
1
2
脚本模式:
1、命令列表
2、引用shell变量需要用双引号
3、#注释
作业1:
写一个自动检测磁盘使用率的脚本,当磁盘使用率达到90%以上时,发邮件给管理员root
作业2:
写一个自动监控系统内存和交换分区使用情况的脚本;当交换分区的剩余空间小于总空间的30%时,提示留意交换分区,否则显示在正常范围
判断IP地址是否合法:
测试如下输入值:
192.168.0.199
95.0.0.1
24.234.2345.1
192.a1.123.0
1a2.1.1.0
01.1.1.1
123
------------------------------------------------------------------------------------------------------------
#!/bin/bash
read -p "请输入IP地址:" IP
#判断所输入的ip地址格式(数字并且是以点分割的4段)
if [[ "$IP" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]];then
ip1=`echo $IP| cut -d. -f1`
ip2=`echo $IP| cut -d. -f2`
ip3=`echo $IP| cut -d. -f3`
ip4=`echo $IP| cut -d. -f4`
else
echo "IP wrong!!!" && exit
fi
#判断所输入的ip第1、4段都不能以0开头;第2、3段可以是0
if [[ "$ip1" =~ ^0 ]] || [[ "$ip4" =~ ^0 ]];then
echo "IP is wrong!" && exit
elif [[ "$ip2" =~ ^0. ]] || [[ "$ip3" =~ ^0. ]];then
echo "IP is wrong!!" && exit
fi
#判断所输入的ip的范围0~255之间
for i in $ip1 $ip2 $ip3 $ip4
do
if [ $i -lt 0 -o $i -ge 255 ];then
echo "ip is not ok" && exit
else
continue
fi
done
#以上条件都不满足则是符合规范的ip
echo "IP is ok!"
-------------------------------------------------------------------------------------------------------------------
如下代码实现如不输入以点分割的4位数,则一直提示输入正确的ip地址,直到输入以点分割的4位后,再判断其他的
#!/bin/bash
fun1(){
ip=""
output_var=$1
while [ -z $ip ] || [[ ! $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]
do
read -p "$output_var" ip
done
echo $ip
}
fun2(){
IP=`fun1 "Input your ipaddr:[192.168.0.1]"`
ip1=`echo $IP| cut -d. -f1`
ip2=`echo $IP| cut -d. -f2`
ip3=`echo $IP| cut -d. -f3`
ip4=`echo $IP| cut -d. -f4`
}
fun2
#判断所输入的ip第1、4段都不能以0开头;第2、3段可以是0
if [[ "$ip1" =~ ^0 ]] || [[ "$ip4" =~ ^0 ]];then
echo "IP is wrong!" && exit
elif [[ "$ip2" =~ ^0. ]] || [[ "$ip3" =~ ^0. ]];then
echo "IP is wrong!!" && exit
fi
#判断所输入的ip的范围0~255之间
for i in $ip1 $ip2 $ip3 $ip4
do
if [ $i -lt 0 -o $i -ge 255 ];then
echo "ip is not ok" && exit
else
continue
fi
#以上条件都不满足则是符合规范的ip
done
echo "IP is ok!"
######################################################
expect 自动应答 TCL(Tool Command Language)语言
# yum install expect -y
# rpm -qi expect
任何有交互性的操作,都可以用expect来做
1. expect 是基于tcl 演变而来的,所以很多语法和tcl 类似,基本的语法如下
#!/usr/bin/expect 首行加上/usr/bin/expect
spawn shell command spawn: 后面加上需要执行的shell 命令,打开一个进程
expect "xxx" expect: 只有spawn 执行的命令结果才会被expect 捕捉到,因为spawn 会启动一个进程,只有这个进程的相关信息才会被捕捉到
send "xxxx" send 会将expect 脚本中需要的信息发送给spawn 启动的那个进程
expect "xxx"
send "xxx"
expect eof 代表结束
执行:
# ./xxx.sh
demo1:使用expect修改用户密码
#!/bin/bash
expect <<EOF &> /dev/null
spawn passwd $1 产生passwd $1这个命令
expect "password:" 当停在password:结尾这个标识符时
send "123\r" 就把123传给它
send "123\r" 当再次停在password:结尾这个标识符时
send "123\r" 就再次把123传给它
expect eof 表示expect结束
EOF
# bash 1.expect test 执行方法,因为脚本里写的是$1,所以后面接你要修改密码的用户名
demo2:使用expect下载同步ftp共享的文件
#!/bin/bash
expect <<EOF &> /dev/null
spawn lftp 10.1.1.254
expect ":~>"
send "get pub/hosts\n"
send "quit\n"
expect eof
EOF
demo3:使用expect实现ssh传密码
#!/bin/bash
sed -i '/^'$1'/d' /root/.ssh/known_hosts
expect << EOF > /dev/null 2>&1
spawn ssh $1
expect "no)?"
send "yes\r"
expect "password:"
send "123456\r"
expect "#"
send "touch /root/Desktop/123\n"
send "exit\n"
expect eof
EOF
说明:关于上面跳过yes的问题,可以加下面的参数来做
ssh 10.1.1.2 -o StrictHostKeyChecking=no
课堂练习:
对多台机器的远程expect操作,假设管理的机器有N台,密码也各不相同(没有ssh等效性),现在需要在所有机器上都创建一个文件为/tmp/zhangsan的文件
# cat ip_user_passwd.list 这个文件里包含你所有管理机器的IP,用户及其对应的密码
10.1.1.11 root 123
10.1.1.22 root 111
10.1.1.33 root 123456
10.1.1.44 root 54321
......
posted @ 2018-06-18 00:38  Sky-wings  阅读(215)  评论(0编辑  收藏  举报