zoukankan      html  css  js  c++  java
  • 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:换行符
    "...":打印字符串
    :制表符
    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 HOME_DIR SEHLL" RS $1" ",$(NF-1)" ",$NF}' passwd1
    (2) USERNAME HOME_DIR SHELL
    **************************************
    # awk -F: 'BEGIN{print "USERNAME HOME_DIR SEHLL" RS "**************************************"};{print $1" ",$(NF-1)" ",$NF}' passwd1
    (3) **************BEGIN******************
    USERNAME HOME_DIR SHELL
    ...
    **************END********************
    # awk -F: 'BEGIN{print "**************BEGIN******************"}RS{print "USERNAME HOME_DIR SHELL" RS,$1" ",$(NF-1)" ",$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 UID HOME_DIR SHELL" RS "****************"};$7~/bash/{print $1" "$3" "$(NF-1)" "$NF};END{print "***********"}' passwd
    【awk -F: 'BEGIN{print "USERNAME UID HOME_DIR SHELL" 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 " 就把123传给它
    send "123 " 当再次停在password:结尾这个标识符时
    send "123 " 就再次把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 "
    send "quit "
    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 "
    expect "password:"
    send "123456 "
    expect "#"
    send "touch /root/Desktop/123 "
    send "exit "
    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
    ......
  • 相关阅读:
    PHP ceil() 函数
    PHP Array 函数
    php中的include()的使用技巧
    [观察者模式]在游戏开发中的应用
    [策略模式]在游戏开发中的应用
    使用EA将源码转化为类图
    PAT 1013 数素数 (20)
    PAT 1034 有理数四则运算(20)
    PAT 1033 旧键盘打字(20)
    PAT 1032 挖掘机技术哪家强(20)
  • 原文地址:https://www.cnblogs.com/skyzy/p/9194227.html
Copyright © 2011-2022 走看看