• awk


    awk
    调用:
    1.调用awk:

    第一种方式:命令行方式
    awk [-F field-separator] 'commands' input-file(s)
    [-F域分隔符]是可选的,因为awk使用空格作为缺省的域分隔符,因此如果要浏览域间有空格的文本,不必指定这个选项,如果要浏览诸如passwd文件,此文件各域以冒号作为分隔符,则必须指明-F选项,如:
    awk -F: 'commands' input-file

    第二种方式是将所有awk命令插入一个文件,并使awk程序可执行,然后用awk命令解释器作为脚本的首行,以便通过键入脚本名称来调用它。

    第三种方式是将所有的awk命令插入一个单独文件,然后调用:
    awk -f awk-scrīpt-file input-files(s)
    -f选项指明在文件awk_scrīpt_file中的awk脚本,input_file(s)是使用awk进行浏览的文件名。 


    模式和动作

    任何awk语句都由模式和动作组成。在一个awk脚本中可能有许多语句。模式部分决定动作语句何时触发及触发事件。处理即对数据进行的操作。如果省略模式部分,动作将时刻保持执行状态。模式可以是任何条件语句或复合语句或正则表达式。模式包括两个特殊字段 BEGIN和END。使用BEGIN语句设置计数和打印头。BEGIN语句使用在任何文本浏览动作之前,之后文本浏览动作依据输入文本开始执行。END语句用来在awk完成文本浏览动作后打印输出文本总数和结尾状态标志。

    域和记录
    使用$1,$3表示参照第1和第3域,注意这里用逗号做域分隔。如果希望打印一个有5个域的记录的所有域,可使用$0,意即所有域。
    为打印一个域或所有域,使用print命令。这是一个awk动作

    模式和动作
    模式:两个特殊断 BEGIN和END
    动作:实际动作大多在{}内指明


    输出
    1.抽取域
    awk -F: '{print $1}' /etc/passwd

    2.保存输出
    awk -F: '{print $1}' /etc/passwd | tee user 使用tee命令,在输出文件的同时,输出到屏幕

    使用标准输出
    awk -F: '{print $1}' /etc/passwd >user3

    4.打印所有记录
    awk -F: '{print $0}' /etc/passwd

    5.打印单独记录
    awk -F: '{print $1,$4}' /etc/passwd

    6.打印报告头
    awk -F: 'BEGIN {print "NAME "} {print $1}' /etc/passwd

    7.打印结尾
    awk -F: '{print $1} END {print "this is all users"}' /etc/passwd


    条件操作符
    1.匹配
    awk -F: '{if($1~/root/) print }' /etc/passwd      //{if($1~/root/) print}表示如果field1包含root,打印它

    2.精确匹配
    使用等号 ==
    awk -F: '{if($3=="0") print }' /etc/passwd  

    3.不匹配
    !~
    awk -F: '{if($1!~/linuxtone/) print }' /etc/passwd

    !=
    精确不匹配
    awk -F: '{if($1!="linuxtone") print }' /etc/passwd

    4.小于
    <
    5.小于等于
    <=
    6.大于
    >
    .........
    7.设置大小写
    awk '/[Rr]oot/' /etc/passwd

    8.任意字符
    awk -F: '{if($1~/^...t/) print}' /etc/passwd      //^...t表示第四个字幕是t

    9.或关系匹配
    awk -F: '{if ($1~/(squid|nagios)/) print}' /etc/passwd

    10.行首
    awk '/^root/' /etc/passwd       // ^root(行首包含root)

    11.AND &&
    awk -F: '{if($1=="root" && $3=="0") print}' /etc/passwd

    12.OR ||

    内置变量:
    ARCC                                      命令行参数个数
    ARGV                                      命令行参数排列
    ENVIRON                                   支持队列中系统环境变量的使用
    FNR                                       浏览文件的记录数
    FS                                        置顶分隔符,等价于-F
    NF                                        浏览记录的域的个数,字段的数目
    NR                                        已读的记录数
    OFS                                       输出域分隔符
    ORS                                       输出记录分隔符
    RS                                        控制记录分隔符

    打印有多少行记录
    awk 'END {print NR}' /etc/passwd

    设置输入域到变量名
    awk -F: '{name=$1; path=$7; if(name~/root/) print name  " path is:" path}' /etc/passwd

    域值比较操作
    awk '{if($6<$7) print $0}' input-file

    修改文本域只显示修改改记录
    awk -F: '{if($1=="nagios") {$1="nagios server" ; print }}' /etc/passwd

    文件长度相加
    ls -l|awk '/^[^d]/ {print $9" " $5} {tot+=$5} END {print "total kb:"tot}'

    内置的字符窜函数
    gsub(r,s)                                                      在整个$0中用s替代r
    gsub(r,s,t)                                                    在整个t中用s替代r
    index(s,t)                                                     返回s中字符串t的第一位置
    length(s)                                                      返回s长度
    match(s,r)                                                     测试s中是否包含匹配r的字符串
    split(s,a,fs)                                                  在fs上将s分成序列a
    sub(s, )                                                       用$0中最左边也是最长的字符串替代
    subtr(s,p)                                                     返回字符串s中从p开始的后缀部分
    substr(s,p,n)                                                  返回字符串s中从p开始长度为n的后缀部分

    1.gsub
    awk 'gsub(/^root/,"netseek") {print}' /etc/passwd             将与root开头的root替换为netseek

    awk 'gsub(/0/,2) {print}' /etc/fstab 

    awk '{print gsub(/0/,2) $0}' /etc/fstab                       

    2.index
    awk 'BEGIN {print index("root","o")}'  查询字符串root中o出现的第一位置

    awk -F: '$1=="root" {print index($1,"o")" "$1}' /etc/passwd

    awk -F: '{print index($1,"o") $1}' /etc/passwd

    3.length
    awk -F: '{print length($1)'} /etc/passwd

    awk -F: '$1=="root" {print length($1)}' /etc/passwd

    4.match (在ANCD中查找C的位置)
    awk 'BEGIN {print match("ANCD",/C/)}'

    5.split
    返回字符串数组元素个数
    awk 'BEGIN {print split("123#456#789", myarray, "#")}'

    6.sub   只能替换指定域的第一个0
    awk 'sub(/0/,2) {print }' /etc/fstab

    7.substr 
    按照起始位置及长度返回字符串的一部分
    awk 'BEGIN {print substr("www.linuxtone.org",5,9)}'  //第5个字符开始,取9个字符。

    awk 'BEGIN {print substr("www.linuxtone.org",5)}'  //第5个位置开始,取后面的所有.

    字符串屏蔽序列
                      退格键
    f                  走纸换页
                      新行
                      回车
                      tab
    c                  任意其他特殊字符
    ddd                八进制

    很简单的例子
    awk -F: '{print $1,""$2," "$3}' /etc/passwd 输出函数printf(注意是printf不是print,两者效果不同的)
    printf函数拥有几种不同的格式化输出功能

    printf修饰符
    -                               左对齐
    Width                        域的步长0表示0步长
    .prec                          最大字符串长度,或小数点右边的位数


    awk printf格式
    %c                              ASCII字符
    %d                              整数
    %e                              浮点数,科学计数法
    %f                               浮点数
    %g                              awk决定使用哪种浮点数转换,e或者f
    %o                              八进制数
    %s                              字符串
    %x                              十六进制数

    1.字符串转换
    echo "65" | awk '{printf"%c ",$0}'

    awk 'BEGIN {printf "%c ",65}'

    awk 'BEGIN {printf "%f ",999}'

    2.格式化输出
    awk -F: '{printf "%-15s %s ",$1,$3}' /etc/passwd

    awk -F: 'BEGIN {printf"USER UID "} {printf "%-15s %s ",$1,$3}' /etc/passwd

    3.向一行awk命令传值
    who | awk '{if ($1 == user) print $1 " you are connected to:" $2}' user=$LOGNAME

    4.awk脚本文件 (在文件名字后面加后缀.awk方便区分)
    #!/bin/awk -f
    BEGIN{
        FS=":"
            print "User UID"
            print"____________________________"
    }

    {printf "%-15s %s ",$1,$3}

    END{
           print "END"

    }

    awk 用法:awk ' pattern {action} '  

    变量名 含义 
    ARGC 命令行变元个数 
    ARGV 命令行变元数组 
    FILENAME 当前输入文件名 
    FNR 当前文件中的记录号 
    FS 输入域分隔符,默认为一个空格 
    RS 输入记录分隔符 
    NF 当前记录里域个数 ,字段的数目
    NR 到目前为止记录数 
    OFS 输出域分隔符 
    ORS 输出记录分隔符 

    1、awk '/101/'               file 显示文件file中包含101的匹配行。 
       awk '/101/,/105/'         file 
       awk '$1 == 5'             file 
       awk '$1 == "CT"'          file 注意必须带双引号 
       awk '$1 * $2 >100 '       file  
       awk '$2 >5 && $2<=15'     file 
    2、awk '{print NR,NF,$1,$NF,}' file 显示文件file的当前记录号、域数和每一行的第一个和最后一个域。 
       awk '/101/ {print $1,$2 + 10}' file 显示文件file的匹配行的第一、二个域加10。 
       awk '/101/ {print $1$2}'  file 
       awk '/101/ {print $1 $2}' file 显示文件file的匹配行的第一、二个域,但显示时域中间没有分隔符。 
    3、df | awk '$4>1000000 '         通过管道符获得输入,如:显示第4个域满足条件的行。 
    4、awk -F "|" '{print $1}'   file 按照新的分隔符“|”进行操作。 
       awk  'BEGIN { FS="[: /t|]" } 
       {print $1,$2,$3}'       file 通过设置输入分隔符(FS="[: /t|]")修改输入分隔符。 

       Sep="|" 
       awk -F $Sep '{print $1}'  file 按照环境变量Sep的值做为分隔符。    
       awk -F '[ :/t|]' '{print $1}' file 按照正则表达式的值做为分隔符,这里代表空格、:、TAB、|同时做为分隔符。 
       awk -F '[][]'    '{print $1}' file 按照正则表达式的值做为分隔符,这里代表[、] 
    5、awk -f awkfile       file 通过文件awkfile的内容依次进行控制。 
       cat awkfile 
    /101/{print "/047 Hello! /047"} --遇到匹配行以后打印 ' Hello! './047代表单引号。 
    {print $1,$2}                   --因为没有模式控制,打印每一行的前两个域。 
    6、awk '$1 ~ /101/ {print $1}' file 显示文件中第一个域匹配101的行(记录)。 
    7、awk   'BEGIN { OFS="%"} 
       {print $1,$2}'           file 通过设置输出分隔符(OFS="%")修改输出格式。 
    8、awk   'BEGIN { max=100 ;print "max=" max}             BEGIN 表示在处理任意行之前进行的操作。 
       {max=($1 >max ?$1:max); print $1,"Now max is "max}' file 取得文件第一个域的最大值。 
       (表达式1?表达式2:表达式3 相当于: 
       if (表达式1) 
           表达式2 
       else 
           表达式3 
       awk '{print ($1>4 ? "high "$1: "low "$1)}' file  
    9、awk '$1 * $2 >100 {print $1}' file 显示文件中第一个域匹配101的行(记录)。 
    10、awk '{$1 == 'Chi' {$3 = 'China'; print}' file 找到匹配行后先将第3个域替换后再显示该行(记录)。 
        awk '{$7 %= 3; print $7}'  file 将第7域被3除,并将余数赋给第7域再打印。 
    11、awk '/tom/ {wage=$2+$3; printf wage}' file 找到匹配行后为变量wage赋值并打印该变量。 
    12、awk '/tom/ {count++;}  
             END {print "tom was found "count" times"}' file END表示在所有输入行处理完后进行处理。 
    13、awk 'gsub(//$/,"");gsub(/,/,""); cost+=$4; 
             END {print "The total is $" cost>"filename"}'    file gsub函数用空串替换$和,再将结果输出到filename中。
        1 2 3 $1,200.00 
        1 2 3 $2,300.00 
        1 2 3 $4,000.00 

        awk '{gsub(//$/,"");gsub(/,/,""); 
        if ($4>1000&&$4<2000) c1+=$4; 
        else if ($4>2000&&$4<3000) c2+=$4; 
        else if ($4>3000&&$4<4000) c3+=$4; 
        else c4+=$4; } 
        END {printf  "c1=[%d];c2=[%d];c3=[%d];c4=[%d]/n",c1,c2,c3,c4}"' file 
        通过if和else if完成条件语句 

        awk '{gsub(//$/,"");gsub(/,/,""); 
        if ($4>3000&&$4<4000) exit; 
        else c4+=$4; } 
        END {printf  "c1=[%d];c2=[%d];c3=[%d];c4=[%d]/n",c1,c2,c3,c4}"' file 
        通过exit在某条件时退出,但是仍执行END操作。 
        awk '{gsub(//$/,"");gsub(/,/,""); 
        if ($4>3000) next; 
        else c4+=$4; } 
        END {printf  "c4=[%d]/n",c4}"' file 
        通过next在某条件时跳过该行,对下一行执行操作。 


    14、awk '{ print FILENAME,$0 }' file1 file2 file3>fileall 把file1、file2、file3的文件内容全部写到fileall中,格式为
        打印文件并前置文件名。 
    15、awk ' $1!=previous { close(previous); previous=$1 }    
        {print substr($0,index($0," ") +1)>$1}' fileall 把合并后的文件重新分拆为3个文件。并与原文件一致。 
    16、awk 'BEGIN {"date"|getline d; print d}'         通过管道把date的执行结果送给getline,并赋给变量d,然后打印。 
    17、awk 'BEGIN {system("echo /"Input your name://c/""); getline d;print "/nYour name is",d,"/b!/n"}'
        通过getline命令交互输入name,并显示出来。 
        awk 'BEGIN {FS=":"; while(getline< "/etc/passwd" >0) { if($1~"050[0-9]_") print $1}}'
        打印/etc/passwd文件中用户名包含050x_的用户名。 

    18、awk '{ i=1;while(i<NF) {print NF,$i;i++}}' file 通过while语句实现循环。 
        awk '{ for(i=1;i<NF;i++) {print NF,$i}}'   file 通过for语句实现循环。     
        type file|awk -F "/" ' 
        { for(i=1;i<NF;i++) 
        { if(i==NF-1) { printf "%s",$i } 
        else { printf "%s/",$i } }}'               显示一个文件的全路径。 
        用for和if显示日期 
        awk  'BEGIN { 
    for(j=1;j<=12;j++) 
    { flag=0; 
      printf "/n%d月份/n",j; 
            for(i=1;i<=31;i++) 
            { 
            if (j==2&&i>28) flag=1; 
            if ((j==4||j==6||j==9||j==11)&&i>30) flag=1; 
            if (flag==0) {printf "%02d%02d ",j,i} 
            } 

    }' 
    19、在awk中调用系统变量必须用单引号,如果是双引号,则表示字符串 
    Flag=abcd 
    awk '{print '$Flag'}'   结果为abcd 
    awk '{print  "$Flag"}'   结果为$Flag

    一、split 初始化和类型强制 

    awk的内建函数split允许你把一个字符串分隔为单词并存储在数组中。你可以自己定义域分隔符或者使用现在FS(域分隔符)的值。
    文件长度相加
    ls -l|awk '/^[^d]/ {print $9" " $5} {tot+=$5} END {print "total kb:"tot}'

    内置的字符窜函数
    gsub(r,s)                                                      在整个$0中用s替代r
    gsub(r,s,t)                                                    在整个t中用s替代r
    index(s,t)                                                     返回s中字符串t的第一位置
    length(s)                                                      返回s长度
    match(s,r)                                                     测试s中是否包含匹配r的字符串
    split(s,a,fs)                                                  把s按照fs分成序列 a[1] a[2]#在fs上将s分成序列a
    sub(s, )                                                       用$0中最左边也是最长的字符串替代
    subtr(s,p)                                                     返回字符串s中从p开始的后缀部分
    substr(s,p,n)                                                  返回字符串s中从p开始长度为n的后缀部分
     
    格式:
    split (string, array, field separator)
    split (string, array) -->如果第三个参数没有提供,awk就默认使用当前FS值。

    例子:
    例1:替换分隔符
    1
    2
    3
    time="12:34:56"
    out=`echo $time| awk '{split($0,a,":");print a[1],a[2],a[3]}'`
    echo $out

    例2:计算指定范围内的和(计算每个人1月份的工资之和)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [root@test~]# cat test.txt
    Tom   2012-12-11car 53000
    John   2013-01-13bike 41000
    vivi 2013-01-18car 42800
    Tom   2013-01-20car 32500
    John   2013-01-28bike 63500
    [root@test~]# awk '{split($2,a,"-");if(a[2]==01){b[$1]+=$4}}END{for(i in b)print i,b[i]}' test.txt
    vivi 2800
    Tom2500
    John4500

    二、substr 截取字符串

    返回从起始位置起,指定长度之子字符串;若未指定长度,则返回从起始位置到字符串末尾的子字符串。
    格式:
    substr(s,p) 返回字符串s中从p开始的后缀部分
    substr(s,p,n) 返回字符串s中从p开始长度为n的后缀部分
    例子:
    1
    2
    [root@test~]# echo "123" | awk '{print substr($0,1,1)}'
    1

    解释:

    awk -F ',' '{print substr($3,6)}' ---> 表示是从第3个字段里的第6个字符开始,一直到设定的分隔符","结束.
    substr($3,10,8) ---> 表示是从第3个字段里的第10个字符开始,截取8个字符结束.
    substr($3,6) ---> 表示是从第3个字段里的第6个字符开始,一直到结尾

    三、length 字符串长度
    length函数返回没有参数的字符串的长度。length函数返回整个记录中的字符数。
    1
    2
    [root@test~]# echo "123" | awk '{print length}'
    3

    四、gsub函数

    gsub函数则使得在所有正则表达式被匹配的时候都发生替换。gsub(regular expression, subsitution string, target string);简称 gsub(r,s,t)。

    举例:把一个文件里面所有包含 abc 的行里面的 abc 替换成 def,然后输出第一列和第三列

    1
    awk '$0 ~ /abc/ {gsub("abc", "def", $0); print $1, $3}'abc.txt

    五、正则表达式

    字符功能
    + 指定如果一个或多个字符或扩展正则表达式的具体值(在 +(加号)前)在这个字符串中,则字符串匹配。命令行:

    awk '/smith+ern/' testfile

    将包含字符 smit,后跟一个或多个 h 字符,并以字符 ern 结束的字符串的任何记录打印至标准输出。此示例中的输出是:

    smithern, harry smithhern, anne

    ? 指定如果零个或一个字符或扩展正则表达式的具体值(在 ?(问号)之前)在字符串中,则字符串匹配。命令行:

    awk '/smith?/' testfile

    将包含字符 smit,后跟零个或一个 h 字符的实例的所有记录打印至标准输出。此示例中的输出是:

    smith, alan smithern, harry smithhern, anne smitters, alexis

    | 指定如果以 |(垂直线)隔开的字符串的任何一个在字符串中,则字符串匹配。命令行:

    awk '/allen | alan /' testfile

    将包含字符串 allen 或 alan 的所有记录打印至标准输出。此示例中的输出是:

    smiley, allen smith, alan

    ( ) 在正则表达式中将字符串组合在一起。命令行:

    awk '/a(ll)?(nn)?e/' testfile

    将具有字符串 ae 或 alle 或 anne 或 allnne 的所有记录打印至标准输出。此示例中的输出是:

    smiley, allen smithhern, anne

    {m} 指定如果正好有 m 个模式的具体值位于字符串中,则字符串匹配。命令行:

    awk '/l{2}/' testfile

    打印至标准输出

    smiley, allen

    {m,} 指定如果至少 m 个模式的具体值在字符串中,则字符串匹配。命令行:

    awk '/t{2,}/' testfile

    打印至标准输出:

    smitters, alexis

    {m, n} 指定如果 m 和 n 之间(包含的 m 和 n)个模式的具体值在字符串中(其中m<= n),则字符串匹配。命令行:

    awk '/er{1, 2}/' testfile

    打印至标准输出:

    smithern, harry smithern, anne smitters, alexis

    [String] 指定正则表达式与方括号内 String 变量指定的任何字符匹配。命令行:

    awk '/sm[a-h]/' testfile

    将具有 sm 后跟以字母顺序从 a 到 h 排列的任何字符的所有记录打印至标准输出。此示例的输出是:

    smawley, andy

    [^ String] 在 [ ](方括号)和在指定字符串开头的 ^ (插入记号) 指明正则表达式与方括号内的任何字符不匹配。这样,命令行:

    awk '/sm[^a-h]/' testfile

    打印至标准输出:

    smiley, allen smith, alan smithern, harry smithhern, anne smitters, alexis

    ~,!~ 表示指定变量与正则表达式匹配(代字号)或不匹配(代字号、感叹号)的条件语句。命令行:

    awk '$1 ~ /n/' testfile

    将第一个字段包含字符 n 的所有记录打印至标准输出。此示例中的输出是:

    smithern, harry smithhern, anne

    ^ 指定字段或记录的开头。命令行:

    awk '$2 ~ /^h/' testfile

    将把字符 h 作为第二个字段的第一个字符的所有记录打印至标准输出。此示例中的输出是:

    smithern, harry

    $ 指定字段或记录的末尾。命令行:

    awk '$2 ~ /y$/' testfile

    将把字符 y 作为第二个字段的最后一个字符的所有记录打印至标准输出。此示例中的输出是:

    smawley, andy smithern, harry

    . (句号) 表示除了在空白末尾的终端换行字符以外的任何一个字符。命令行:

    awk '/a..e/' testfile

    将具有以两个字符隔开的字符 a 和 e 的所有记录打印至标准输出。此示例中的输出是:

    smawley, andy smiley, allen smithhern, anne

    *(星号) 表示零个或更多的任意字符。命令行:

    awk '/a.*e/' testfile

    将具有以零个或更多字符隔开的字符 a 和 e 的所有记录打印至标准输出。此示例中的输出是:

    smawley, andy smiley, allen smithhern, anne smitters, alexis

    (反斜杠) 转义字符。当位于在扩展正则表达式中具有特殊含义的任何字符之前时,转义字符除去该字符的任何特殊含义。例如,命令行:

    /a///

    将与模式 a // 匹配,因为反斜杠否定斜杠作为正则表达式定界符的通常含义。要将反斜杠本身指定为字符,则使用双反斜杠。有关反斜杠及其使用的更多信息,请参阅以下关于转义序列的内容。

    举例:把一个文件里面所有包含 abc 的行里面的 abc 替换成 def,然后输出第一列和第三列

    1
    awk '$0 ~ /abc/ {gsub("abc", "def", $0); print $1, $3}'abc.txt
  • 相关阅读:
    (转)Linux: su sudo sudoer
    unsigned 和 signed
    (转)原码, 反码, 补码 详解
    判断两个链表是否相交
    源代码里面看不到页面展示的数据?原因何在
    python 小技巧 防止SSL报错信息
    python爬虫之一---------豆瓣妹子图
    服务端性能测试 TPS
    H5性能测试学习
    App测试中 ----------------Android和IOS测试区别
  • 原文地址:https://www.cnblogs.com/zhaozhenguo666/p/5512768.html
Copyright © 2020-2023  润新知