zoukankan      html  css  js  c++  java
  • awk

    声明一个关联数组变量:
    declare -A  a
                 -a  
                 -i    整数变量
                 -r   只读变量
                 -x  全局变量
    awk  'BEGIN{a["mon"]=monday;a["sun"]=sunday;print a["mon"]}'
     
     
    awk 'BEGIN{b[0]="monday"; b[1]="sunday";for  (i=0;i<=1;i++) {print b[i]}}'
     
    一、print
    print的使用格式:
    print item1, item2, ...
    要点:
    1、各项目之间使用逗号隔开,而输出时则以空白字符分隔;
    2、输出的item可以为字符串或数值、当前记录的字段(如$1)、变量或awk的表达式;数值会先转换为字符串,而后再输出;
    3、print命令后面的item可以省略,此时其功能相当于print $0, 因此,如果想输出空白行,则需要使用print "";
     
    例子:
    # awk 'BEGIN { print "line one line two line three" }'
    awk -F: '{ print $1, $3 }' /etc/passwd
     
     
    二、awk变量
     
    2.1 awk内置变量之记录变量:
    FS: field separator,读取文件本时,所使用字段分隔符;
    RS: Record separator,输入文本信息所使用的换行符;
    OFS: Output Filed Separator: 
    ORS:Output Row Separator:
     
    awk -F:
    OFS="#"
    FS=":"
     
     
    2.2 awk内置变量之数据变量:
    NR: The number of input records,awk命令所处理的记录数;如果有多个文件,这个数目会把处理的多个文件中行统一计数;
    NF:Number of Field,当前记录的field个数;
    FNR: 与NR不同的是,FNR用于记录正处理的行是当前这一文件中被总共处理的行数;
    ARGV: 数组,保存命令行本身这个字符串,如awk '{print $0}' a.txt b.txt这个命令中,ARGV[0]保存awk,ARGV[1]保存a.txt;
    ARGC: awk命令的参数的个数;
    FILENAME: awk命令所处理的文件的名称;
    ENVIRON:当前shell环境变量及其值的关联数组;
     
    如:awk 'BEGIN{print ENVIRON["PATH"]}'
     
    2.3 用户自定义变量
     
    gawk允许用户自定义自己的变量以便在程序代码中使用,变量名命名规则与大多数编程语言相同,只能使用字母、数字和下划线,且不能以数字开头。gawk变量名称区分字符大小写。
     
    2.3.1 在脚本中赋值变量
     
    在gawk中给变量赋值使用赋值语句进行,例如:
    awk 'BEGIN{var="variable testing";print var}'
    awk  'BEGIN{a="country";print a}'
    centos6.4经验证,脚本中变量值为字符串类型时,必须加双引号""才能正常打印。
     
    2.3.2 在命令行中使用赋值变量
     
    gawk命令也可以在“脚本”外为变量赋值,并在脚本中进行引用。例如,上述的例子还可以改写为:
    #awk -v var="variable testing" 'BEGIN{print var}'
    #awk  'BEGIN{a=2} {print a}'  file
    #awk  'a=2  {print a}'  file
    #free | sed -n '2p'| awk   'x=int(($3/$2)*100) {print x}' | sed  's/$/%/'
     
    三、printf
    printf命令的使用格式:
    printf format, item1, item2, ...
    # printf  "%-12s  %6i " qwert 110
    要点:
    1、其与print命令的最大不同是,printf需要指定format;
    2、format用于指定后面的每个item的输出格式;
    3、printf语句不会自动打印换行符;
     
    format格式的指示符都以%开头,后跟一个字符;如下:
    %c: 显示字符的ASCII码;
    %d, %i:十进制整数;
    %e, %E:科学计数法显示数值;
    %f: 显示浮点数;
    %g, %G: 以科学计数法的格式或浮点数的格式显示数值;
    %s: 显示字符串;
    %u: 无符号整数;
    %%: 显示%自身;
     
    修饰符:
    N: 显示宽度;
    -: 左对齐;
    +:显示数值符号;
     
    例子:
    # awk  -F:  '{printf "%-15s %i ",$1,$3}' /etc/passwd
    # printf  "%-20s       %.4f " dingzhao 110.1100980
    四、输出重定向
     
    print items > output-file
    print items >> output-file
    print items | command
     
    特殊文件描述符:
    /dev/stdin:标准输入
    /dev/sdtout: 标准输出
    /dev/stderr: 错误输出
    /dev/fd/N: 某特定文件描述符,如/dev/stdin就相当于/dev/fd/0;
     
    例子:
    # awk -F: '{printf "%-15s %i ",$1,$3 > "/dev/stderr" }' /etc/passwd
     
     
    六、awk的操作符:
     
    6.1 算术操作符:
     
    -x: 负值
    +x: 转换为数值;
    x^y: 
    x**y: 次方
    x*y: 乘法
    x/y:除法
    x+y:
    x-y:
    x%y:
     
    6.2 字符串操作符:
    只有一个,而且不用写出来,用于实现字符串连接;
     
    6.3 赋值操作符:
    =
    +=
    -=
    *=
    /=
    %=
    ^=
    **=
     
    ++
    --
     
    需要注意的是,如果某模式为=号,此时使用/=/可能会有语法错误,应以/[=]/替代;
     
    6.4 布尔值
     
    awk中,任何非0值或非空字符串都为真,反之就为假;
     
    6.5 比较(关系)操作符:
    x < y True if x is less than y. 
    x <= y True if x is less than or equal to y. 
    x > y True if x is greater than y. 
    x >= y True if x is greater than or equal to y. 
    x == y True if x is equal to y. 
    x != y True if x is not equal to y. 
    x ~ y True if the string x matches the regexp denoted by y. 
    x !~ y True if the string x does not match the regexp denoted by y. 
    subscript in array   True if the array array has an element with the subscript subscript.
     
    6.7 表达式间的逻辑关系符:
    &&
    ||
    !
    6.8 条件表达式:
    selector?if-true-exp:if-false-exp
     
    if selector; then
      if-true-exp
    else
      if-false-exp
    fi
     
    三目运算符:
    a=2
    b=1
    c=$(($a<$b?$a:$b))
    echo $c
     
    6.9 函数调用:
    function_name(para1,para2)
     
     
     
     
    七 awk的模式:
     
    awk 'program' input-file1 input-file2 ...
    其中的program为:
    pattern { action }
    pattern { action }
    ...
     
    7.1 常见的模式类型:
    1、Regexp: 正则表达式,格式为/regular expression/
    2、expresssion: 表达式,其值非0或为非空字符时满足条件,如:$1 ~ /foo/ 或 $1 == "magedu",用运算符~(匹配)和!~(不匹配)。
    3、Ranges: 指定的匹配范围,格式为pat1,pat2
    4、BEGIN/END:特殊模式,仅在awk命令执行前运行一次或结束前运行一次
    5、Empty(空模式):匹配任意输入行;
     
    7.2 常见的Action
    1、Expressions:
    2、Control statements
    3、Compound statements
    4、Input statements
    5、Output statements
     
     
    /正则表达式/:使用通配符的扩展集。
     
    关系表达式:可以用下面运算符表中的关系运算符进行操作,可以是字符串或数字的比较,如$2>%1选择第二个字段比第一个字段长的行。
     
    模式匹配表达式:
     
    模式,模式:指定一个行的范围。该语法不能包括BEGIN和END模式。
     
    BEGIN:让用户指定在第一条输入记录被处理之前所发生的动作,通常可在这里设置全局变量。
     
    END:让用户在最后一条输入记录被读取之后发生的动作。
     
     
     
     
     
    八 控制语句:
    8.1 if-else
    语法:if (condition) {then-body} else {[ else-body ]}
    # awk  -F:  '{if ($3==0) {print $1, "Adminitrator"} else { print $1,"Common User"}}' /etc/passwd
    例子:
    awk -F: '{if ($1=="root") print $1, "Admin"; else print $1, "Common User"}' /etc/passwd
    awk -F: '{if ($1=="root") printf "%-15s: %s ", $1,"Admin"; else printf "%-15s: %s ", $1, "Common User"}' /etc/passwd
    awk -F: -v sum=0 '{if ($3>=500) sum++}END{print sum}' /etc/passwd
    awk -F: '{if ($3==0) {print $1,"admin";print "it is root"} else print $1,"common-user"}' /etc/passwd |less
    awk -F: '{if($1=="root"){print "root"}else if($1=="bin"){print "bin"}else{print "game over"} }'  /etc/passwd
    awk 'BEGIN {FS=":"} { if ($3 >= 30 && $3 <= 40) {print  $0}}' /etc/passwd
     
     
     
     
    8.2 while
    语法: while (condition){statement1; statment2; ...}
    awk -F: '{i=1;while (i<=3) {print $i;i++}}' /etc/passwd
    awk -F: '{i=1;while (i<=NF) { if (length($i)>=4) {print $i}; i++ }}' /etc/passwd
    awk '{i=1;while (i<=NF) {if ($i>=100) print $i; i++}}' hello.txt
     
    hello.txt文件的内容为一堆随机数。
     
    语法: do {statement1, statement2, ...} while (condition)
    8.3 do-while 至少执行一次循环体,不管条件满足与否
    awk -F: '{i=1;do {print $i;i++}while(i<=3)}' /etc/passwd
    awk -F: '{i=4;do {print $i;i--}while(i>4)}' /etc/passwd
     
    8.4 for
    语法: for ( variable assignment; condition; iteration process) { statement1; statement2;...}
    awk -F: '{for(i=1;i<=3;i++) print $i}'   /etc/passwd
    awk -F: '{for(i=1;i<=NF;i++) { if (length($i)>=4) {print $i}}}'    /etc/passwd
     
    for循环还可以用来遍历数组元素:
    语法: for (i in array) {statement1;statement2; ...}
    awk -F:  '$NF!~/^$/{BASH[$NF]++}  END{for(A in BASH)  {printf "%15s:%i ",A,BASH[A]}}'    /etc/passwd
     
    BASH[/bin/bash]++
     
    BASH[/sbin/nologin]
     
    BASH[/bin/bash]=1
    BASH[/sbin/nologin]=2
    BASH[/bin/sync]=1
     
    /bin/bash: 1
    /sbin/nologin: 2
    /bin/sync: 1
     
    8.5 case
    语法:switch (expression) { case VALUE or /REGEXP/: statement1, statement2,... default: statement1, ...}
    switch语句在CentOS7系列中使用正常,在6中使用会报错误提示
     
    8.6 break 和 continue
    常用于循环或case语句中
     
    8.7 next
    提前结束对本行文本的处理,并接着处理下一行;例如,下面的命令将显示其ID号为奇数的用户:
    # awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd
     
     
    九 awk中使用数组
     
    9.1 数组
    声明一个关联数组:declare -A arr
    array[index-expression]
     
    index-expression可以使用任意字符串;需要注意的是,如果某数据组元素事先不存在,那么在引用其时,awk会自动创建此元素并初始化为空串;因此,要判断某数据组中是否存在某元素,需要使用index in array
     
    的方式。
     
    要遍历数组中的每一个元素,需要使用如下的特殊结构:
    for (var in array) { statement1, ... }
    其中,var用于引用数组下标,而不是元素值
     
    例子:
    netstat   -ant | awk '/^tcp/ {S[$NF]++}   END {for(a in S) print a, S[a]}'
    每出现一被/^tcp/模式匹配到的行,数组S[$NF]就加1,NF为当前匹配到的行的最后一个字段,此处用其值做为数组S的元素索引;
     
    awk   '{counts[$1]++}; END {for(url in counts) print counts[url], url}'   /var/log/httpd/access_log
    用法与上一个例子相同,用于统计某日志文件中IP地的访问量
     
    获取数组的长度:${#arr[*]}或者${#arr[@]}
    获取数组的下标(key):${!arr[*]}或者${!arr[@]}
     
     
     
     
     
     
    9.2 删除数组变量
     
    从关系数组中删除数组索引需要使用delete命令。使用格式为:
     
    delete  array[index]
     
     
     
    十、awk的内置函数
     
    split(string, array [, fieldsep [, seps ] ])转换为数组
    功能:将string表示的字符串以fieldsep为分隔符进行分隔,并将分隔后的结果保存至array为名的数组中;数组下标为从1开始的序列;
    root:x:0:0:root:/root:/bin/bash
     
    user[1]=root
    user[2]=x
    ...
    user[7]=/bin/bash
     
     
     
    # netstat -ant | awk '/:80>/{split($5,clients,":");IP[clients[1]]++}END{for(i in IP){print IP[i],i}}' | sort -rn | head -50
     
    # netstat -tan | awk '/:80>/{split($5,clients,":");ip[clients[4]]++}END{for(a in ip) print ip[a],a}' | sort -rn | head -50
     
    # df -lh | awk '!/^File/{split($5,percent,"%");if(percent[1]>=20){print $1}}'
     
    length([string])
    功能:返回string中变量,字符串中字符的个数;
    awk -v hello=aaaaaaa 'BEGIN{print length(hello)}'//返回7
    awk 'BEGIN{print length("abcdef")}'//返回6,字符串得加双引号。
    awk 'BEGIN{print length(1234)}'//返回4
     
    substr(string, start [, length])字符串截取
    功能:取string字符串中的子串,从start开始,取length个;start从1开始计数;
     awk  'BEGIN{a="country";print substr(a,5,3)}'
    awk脚本中涉及到下标的都是从1开始排序,而不是从0.
     
    sub(),gsub()字符串替换
    [root@localhost ~]# netstat -antp |awk 'BEGIN{a="herhim";sub(/h/,"A",a);print a}'
    Aerhim
    [root@localhost ~]# netstat -antp |awk 'BEGIN{a="herhim";gsub(/h/,"A",a);print a}'
    AerAim
     
    [root@agent1 ~]# cat data1
    1 3 3
    2 4 6 
    3 6 8 
    [root@agent1 ~]# awk '{sub(/w/,"00&");print $0}' data1     <sub()函数里以正则表达式匹配时,必须放在/../里>
    001 3 3
    002 4 6 
    003 6 8 
    [root@agent1 ~]# awk '{sub($2,"00&");print $0}'  data1
    1 003 3
    2 004 6 
    3 006 8 
    [root@agent1 ~]# awk '{sub(4,"00&");print $0}'  data1
    1 3 3
    2 004 6 
    3 6 8 
     
     
     
     
    三元表达式awk 'BEGIN{c=2<1?0:100;print c}'
     
     
     
    system("command")
    功能:执行系统command并将结果返回至awk命令
     
    systime()
    功能:取系统当前时间戳
    #awk  'BEGIN{date=systime();day=strftime("%F %T",date);print day}'
    #awk  'BEGIN{print strftime("%F %T",1464847888)}'把某个时间戳格式化输出。
    #awk  'BEGIN{print strftime("%F %T")}'格式化输出当前时间。
     
    tolower(s)
    功能:将s中的所有字母转为小写
    [root@localhost ~]# awk  'BEGIN{a="country";print tolower(a)}'
    country
    [root@localhost ~]# awk  'BEGIN{a="country";print toupper(a)}'
    COUNTRY
    toupper(s)
    功能:将s中的所有字母转为大写
     
    十一、用户自定义函数
    自定义函数使用function关键字。格式如下:
    function F_NAME([variable])
    {
    statements
    }
    函数还可以使用return语句返回值,格式为“return value”。
    #awk  'function F1() {print "hello,world"}  BEGIN{F1()}'
     
    函数库:
    file1文件里定义了若干个函数:
    function info() {
      name="dingzhao"
      age=28
      print name
      print age
    }
     
    function date() {
       time=systime()
       day=strftime("%F %T",time)
       print day
    }
     
    脚本文件file2:
    BEGIN{info();date();print "over"}
     
    #awk -f file1 -f file2,输出如下:
    dingzhao
    28
    2016-03-30 16:29:11
    over
    注意:-f 参数不能与awk内联脚本放到一起使用,可使用多个-f命令行参数解决。以下形式无效:
    #awk -f 1.sh 'BEGIN{info();date();print "over"}'
     
    awk脚本文件传递参数:
    #awk  -f 3.txt  arg1=value1 arg2=value2  /etc/passwd
    在sh脚本文件中给awk程序传递变量参数:
    #awk  -f 3.txt  arg1=$1  arg2=$2  /etc/passwd
     
    还可以通过内置数组ARGV读取命令行参数:
    #awk -f 1.awk  dingzhao 31
    #cat 1.awk

    function a(){
    print ARGV[1]
    print ARGV[2]
    }

    BEGIN{a()}

     
    (公开课笔记):
    只显示第一行:awk  -F':'    'NR==1 {print $0}'   /etc/passwd
    只显示最后一行:awk -F':'  'END{print $0}'  /etc/passwd
    只显示最后一列:awk -F':'  '{print $NF}'  /etc/passwd
    不显示第一行: awk  -F':'    'NR!=1'  /etc/passwd
    不显示最后一列:awk -F':'   -v OFS=':'  '{NF--;print $0}'    /etc/passwd
     
     
    练习:1、统计当前系统上每个客户端IP的连接中处于TIME_WAIT的连接状态的个数;
               2、统计ps aux命令执行时,当前系统上各状态的进程的个数;
               3、统计ps aux命令执行时,当前系统上各用户的进程的个数;
        4、显示ps aux命令执行时,当前系统上其VSZ(虚拟内存集)大于10000的进程及其PID;
              5,统计每行的总数;
     [root@agent1 ~]# cat data1
    1 3 5 
    2 4 6 
    3 6 8 
    #awk '{for(i=1;i<=NF;i++){sum[NR]+=$i}} END{for(a in sum){print a,sum[a]}}' data1 或
    #awk '{print NR": "$1+$2+$3}' data1 或
    #awk '{sum=0;for(i=1;i<=NF;i++){sum+=$i};print NR":"sum}' data1
     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    Android标题栏最右边添加按钮
    Activity标题栏添加返回按钮
    【Android】解决Android横竖屏切换数据丢失问题的方法
    Android热更新,到底是更新啥?
    vm ware 虚拟WIN10 时,chrome ,cent browser 显示异常,花屏
    动态生成的 select option 无法选中,设置值
    安装sql 2012 时遇到“需要更新的以前的 Visual Studio 2010 实例。”规则失败。
    C#.NET 简单使用log4net
    10位,13位时间戳转为C#格式时间
    C# .NET Unix 时间戳
  • 原文地址:https://www.cnblogs.com/as007012/p/10009093.html
Copyright © 2011-2022 走看看