欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

马哥 37_04 _awk入门及进阶【攻城狮论坛の免费分享】 有大用

[root@mail ~]# vim health_check5.sh        #以前 health_check4.sh逻辑上有小bug,此时修正了,就是在initstatus这个方法里代码有变化 

#!/bin/bash

#

VIP=192.168.0.77

CPORT=80

FAIL_BACK=127.0.0.1

RS=("192.168.0.45" "192.168.0.55")

declare -a RSSTATUS

RW=("2" "1")

RPORT=80

TYPE=g

CHKLOOP=3

LOG=/var/log/ipvsmonitor.log

addrs() {

        ipvsadm -a -t $VIP:$CPORT -r $1:$RPORT -$TYPE -w $2

        [ $? -eq 0 ] && return 0 || return 1

}

delrs() {

        ipvsadm -d -t $VIP:$CPORT -r $1:$RPORT

        [ $? -eq 0 ] && return 0 || return 1

}

checkrs() {

        local I=1

        while [ $I -le $CHKLOOP ]; do

                if curl --connect-timeout 1 http://$1 &> /dev/null; then

                        return 0

                fi

                let I++

        done

        return 1

}


initstatus() {

        local I

        local COUNT=0

        for I in ${RS[*]}; do

                if ipvsadm -L -n | grep "$I:$RPORT" &> /dev/null; then    #初始化的时候就默认认定所有rs在线

                        RSSTATUS[$COUNT]=1

                else

                        RSSTATUS[$COUNT]=0

                fi

                let COUNT++

        done

}


initstatus

while :; do

        let COUNT=O

        for I in ${RS[*]}; do

           if checkrs $I; then

                if [ ${RSSTATUS[$COUNT]} -eq 0 ]; then

                                addrs $I ${RW[$COUNT]}

                [ $? -eq 0 ] && RSSTATUS[$COUNT]=1 && echo "`date +'%F %H:%M:%S'` , $I is back ." >> $LOG

                fi

          else

                if [ ${RSSTATUS[$COUNT]} -eq 1 ]; then

                        delrs $I

                        [ $? -eq 0 ] && RSSTATUS[$COUNT]=0 && echo "`date +'%F %H:%M:%S'` , $I is gone." >> $LOG

                fi

         fi

        let COUNT++

        done

        sleep 5

done

   



                


grep:文本过滤器

        grep 'pattern' input_file ...

sed: Stream Editor 流编辑器,能实现对文本进行编辑

awk: 作者名字的缩写 a.k.a.??看不懂  Aho,Kernighan and Weinberger

        报告工具,报告生成器,也是一个文本处理工具,主要功能是从文本文件中抽取符合条件的信息,并以特定格式显示出来的这么一个特殊的工具    (格式化以后,显示)

nawk: new awk,早期在soris上比较常见,

gawk:gnu awk, 是linux上实现的awk,一定程度上是兼容nawk和awk的,又有许多其它功能,在有些使用风格上,并不与posik完全兼容


[root@mail ~]# which awk

/bin/awk

[root@mail ~]# ls -la /bin/awk    #看到了吧 ,/bin/awk 只是 gawk的快捷方式而己

lrwxrwxrwx 1 root root 4 2019-07-12 /bin/awk -> gawk

[root@mail ~]#




# awk [options] 'script' file1, file2,...

# awk [options] 'PATTERN { action }' file1, file2,...        script(或者叫postgram)=PATTERN { action }

       打印命令 print普通的简单的显示格式,把要显示的条目逐个显示        

                      printf,可以自定义显示格式(比如位宽,(显示时的宽度);左对齐还是右对齐, 显示字符串不是显示数字)

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png


image.png

image.png

image.png

image.png

image.pngimage.png

image.png


awk的输出:

一、print

print的使用格式:

print iteml, item2, ...

要点:

1、各项目之间使用逗号隔开(逗号相当于连字符?),而输出时则以空白字符分隔:

2、输出的item可以为字符串或数值、当前记录的字段(如$1)、变量或awk的表达式:数值会先转换为字符串,而后再输出:

3、print命令后面的item可以省略,此时其功能相当于print $0,因此,如果想输出空白行,则需要使用print“:

例子:

# avk 'BEGIN { print "line one\nline two\nline three" }'

awk -F: "{ print $1, $2 }" /etc/passwd   #-F: 意思是指定分隔符为冒号






awk根据我们所定义的模式,一次从文件中读取一行文本,相应的对其进行切片,将每一行按照字符串的分隔符(默认是空白字符,不管是几个空白字符)进行切割,

比如 this is a  test.

被切割成了4片,每个片断在awk内部可以使用一个变量来引用,这个变量完全类似于脚本的位置参数变量

$1 $2 $3 $4

$0 (bash脚本中表示脚本名称自身,awk中$0表示一整行)


$1 $2 $3 $4 $0 叫做item,所打印的项目(条目),敲代码时它们之间使用逗号分隔(print item1,item2...),输出的时候仍然是空白字符分隔的

awk 最终要输出屏幕显示出来,打印出来的分隔符,仍然默认是空白字符

awk 所有的动作要在花括号(大括号)当中,而且这一切要使用单引号引起来

-F: ( --field-separator) 输入分隔符;指定分隔符  默认空白字符是分隔符,可以额外指定分隔符,(像cut一样)

'BEGIN{OFS="#"}{action}'  :  (OFS: output field separator) 指定输出分隔符 

                                            这里BEGIN是一个使用模式

{print $1,"hello",$2,$3,$4}    : print 补上字符串,用双引号,逗号隔开


awk内置变量之记录变量

FS: field separater:读取文本时,所使用的字段分隔符,默认是空白字符

RS: Record separater:(Record可以看作是Row)输入文本信息所使用的换行符,默认是换行符,行分隔符,换行符,可以使用完全不同的分隔符,可以把两行当作一行来读,把整个文件当作一行来读,只要明确说明换行符不是回车符就行

OFS:Output Field Separator:输出字段分隔符

ORS:Output Row ( Record ) Separator:输出行分隔符


OFS="#"   : 输出分隔符

FS=":"   :  表示以冒号作为输入分隔符

awk内置变量之数据变量

NR: The number of input records,awk命令所处理的(已处理过的)记录数(行数),如果有多个文件,这个数目会把处理的多个文件中行统一计数

FNR: 这里F表示file文件, awk命令所处理的(已处理过的)所在的当前文件的行数

NF: number of field,当前这一行的字段个数


2.3用户自定义变量

gavk允许用户自定义自己的变量以便在程序代码中使用,变量名命名规则与大多数编程语言相同,只能使用字母、数字和下划线,且不能以数字开头。gawk变量名称区分字符大小写.

2.3.1在脚本中赋值变量 (BEGIN后面的action中赋值)

在gawk中给变量赋值使用赋值语句进行,例如:

awk 'BEGIN{var="variable testing" ;print var}'

2.3.2在命令行中使用赋值变量

gawk命令也可以在“脚本”外为变量赋值,并在脚本中进行引用。例如,上述的例子还可以改写为:

awk -v var="variable testing" 'BEGIN{print var}'


printf

    不会换行,如果想换行,在格式中加上反斜线n(\n) 例如 awk -F '{printf "%-15s %i\n",$1,$3}' /etc/passwd

    printf format,item1,item2,item3,....  先是格式,项目1,项目2,.......

        format 格式当中,字符串和字符串之间(也就是百分号%之间)不需要使用逗号来进行分隔的,,字符串之间(也就是百分号%之间)的符号就是其真正的显示出来的符号,所以可以任意字符符号吧(当然百分号%,中短横,c,d,e,f等等这些特殊字符除外)(要想显示这些特殊字符,两个%%,就是显示百分号%吧,百度一下吧)

        format 格式以百分号%开头,后跟一个字符:

            %c,显示字符的ASCII码,     默认是右对齐, %-c左对齐显示

            %d,%i,显示十进制整数 d(digit) i(integer)

            %e,%E,表示科学计数法显示数据     e (科学计数法符号);在科学计数法中,为了使公式简便,可以用带“E”的格式表示。例如1.03乘10的8次方,可简写为“1.03E+08”的形式  , E代表的英文是 exponent

            %f,显示浮点数 float

            %c,显示字符的ASCII码,

            %g,%G,以科学计数法的格式或浮点数的格式显示数值

            %s,显示字符串

            %u,无符号整数    unsigned integer

            %%,显示百分号%自身


修饰符

N:显示宽度,是一个数字 (number)   默认一个字符只有一个字符的宽度,使用N表示多少位的显示宽度

-:减号左对齐,默认是右对齐

+:加号显示数值符号



awk操作符:

    支持算术表达式

        -x:负值

        +x:转换为数值

        x^y:次方

        x**y:次方

        x*y:乘法

        x/y:除法

        x+y

        x-y

        x%y


    支持赋值操作符        

        =

        +=

        -=

        /=

        %=

        ^=

        **=

        ++

        --

        

    支持比较操作符        

        x < y

        x <= y

        x > y

        x >= y

        x == y

        x != y    不等于

        x ~ y    x是字符串,y是正则表达式模式,如果被匹配到,就为真;否则为假

        x !~ y    与上面相反,匹配不到才为真,匹配到为假

        subscript in array     数组中有对应的元素下标就为真,否则为假(subscript 是数组的下标,不是数组的值)


        && 逻辑与

        ||     逻辑或

        !     逻辑非


        三元操作符    (三目操作符)

            selector?if-true-exp:if-false-exp

                原理bash  if selector; then

                                if-true-exp

                        else

                                if-false-exp

                        if

                    a=3

                    b=4

                    a>b? a is max: b is max

                    

 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   从第几行到第几行(不对)从第几个模式到第几个模式?

                 例  # awk -F: '$3==0,$7~"nologin$"{print $1,$3,$7}' /etc/passwd    # 匹配第一个 $3=0,第一个$7以nologin$结尾的之间的行,打印出第一列,第三列,第七列

4、BEGIN/END: 特殊模式,仅在awk命令执行前运行一次或结束前运行一次 (正常情况下awk读取文件每读一行,运行一次)

5、Empty(空模式): 匹配任意输入行:      什么模式都没有     


7.2常见的Action      最常见的是 print ,printf

1.  Expressions:表达式有 赋值表达式,判断表达式等等

2、Control statements:控制语句    if ,while ,for,do while,case,甚至可以自定义函数

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 ]}        

    #条件condition,小括号,前后不需要带空格, 如果满足条件,花括号括起来;;;只有一个语句,不需要使用花括号括起来

awk -F: '{if ($1=="root") print $1, "Admin"; else print $1, "Common User"}' /etc/passwd # 如果用户名($1)为root,输出$1为管理员,否则就是普通用户

awk -F: '{if ($1=="root") printf  "%-15s:  %s\n", $1,"Admin"; else printf  "%-15s:  %s\n",$1,"Common User"}' /etc/passwd

awk -F: -v sum=0 '{if ($3>=500) sum++}END{print sum}' /etc/passwd    #id大于等于500的所有用户的个数


8.2 while        #awk本身是一行一行的循环处理的,所以这里 while 就是循环每一行中的字段

语法: while (condition){statement1; statment2; ...}

awk -F:  '{i=1;while (i<=3) {print $i;i++}}' /etc/passwd            #打印出所有行的第1列,第2列,第3列

awk -F:  '{i=1;while (i<=NF){ if (length($i)>=4) print $i;i++ }}'  /etc/passwd  #将每个字段长度大于等于4的打印出来

8.3 do-while    #类似于C语言风格的循环, 与 while 区别是不管是否满足条件,先执行一遍

语法: do {statement1, statement2, ...} while (condition)

awk -F: '{i=1;do {print $i;i++} while(i<=3)}' /etc/passwd     #打印出所有行的第1列,第2列,第3列

8.4 for

语法: for ( variable assignment; condition; iteration process) { statement1, statement2, ...}

awk -F: '{for(i=1;i<=3;i++) print $i}' /etc/passwd             #打印出所有行的第1列,第2列,第3列

awk -F: '{for(i=1;i<=NF;i++){if(length($i)>=4) print $i }}' /etc/passwd         #每一行的字段中;字符长度大于等于4的才显示出来,,,for循环的并不是行,而是行中的字段

for循环还可以用来遍历数组元素:  #记住 这里 i 是数组的下标,不是数组的元素里的值

语法: for (i in array) {statement1, statement2, ...} 


awk -F: '$NF!~/^$/{BASH[$NF]++}END{for(A in BASH){printf "%15s:%i\n",A, BASH[A]}}' /etc/passwd        #看看使用哪种登录程序的个数  /^$/表示空白吧     /^$/的意思 难道与 "^$" 意思一样,

                                                "/^$/"的意思 表示 

    [root@mail ~]# awk -F: '$NF~"^$"{BASH[$NF]++}END{for(A in BASH){printf "%15s:%i\n",A, BASH[A]}}' /etc/passwd #能匹配到空

                   :1

    [root@mail ~]# awk -F: '$NF~"/^$/"{BASH[$NF]++}END{for(A in BASH){printf "%15s:%i\n",A, BASH[A]}}' /etc/passwd    #不能匹配到空

    [root@mail ~]# awk -F: '$NF~/^$/{BASH[$NF]++}END{for(A in BASH){printf "%15s:%i\n",A, BASH[A]}}' /etc/passwd  #能匹配到空

                   :1

    [root@mail ~]#



8.5 case

语法: switch (expression) { case VALUE or /REGEXP/: statement1,break; case VALUE or /REGEXP/: staterment2,break; ... default: statement1, ...}

#switch后面 小括号括起来的表达式(expression是表达式)


8.6 break和continue   #continue   是提前结束本字段的

常用于循环或case语句中


8.7 next        #提交结束本行的,相当于awk自己内部的continue

提前结束对本行文本的处理,并接着处理下一行:例如,下面的命令将显示其ID号为奇数的用户:

营awk -F: '{if($3%2=0) next;print $1,$3}' /etc/passwd        # 这里 $3 即第三列,是uid号



九  awk中使用数组

9.1数组

array[index-expression]

index- expression可以使用任意字符串:需要注意的是,如果某数据组元素事先不存在,那么在引用其时,awk会自动创建此元素并初始化为空串,因此,要判断某数据组中是否存在某元素下标,需要使用index in array的方式。

    awk数组下标从1开始(bash是从0开始的);awk数组下标可以自己完全定义(可以使用任意字符串),不一定非要使用数字

要遍历数组中的每一个元素, 需要使用如下的特殊结构:

        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为当前匹配到的行的最后一个字段(这里是状态值 如 ESTABLIESHED等), 此处用其值做为数组S的元素索引:

        awk '{count[$1]++}; END {for(url in count) print  url, count[url],}' /var/1og/httpd/access log 

用法与上一一个例子相间,用于统计某日志文件中客户端IP的访问量  $1这里指的是客户端的ip


        awk中,变量的初始值为0

        数组可以直接使用,不用声明        

            state[abc]=3

            state[efg]=6

            for (A in state) {print A, state[A]}

        

9.2删除数组变量

从关系数组中删除数组索引需要使用delete命令。使用格式为: 

delete array[ index]






image.png

image.png

[root@mail ~]# vim test.txt

this is a test.


[root@mail ~]# awk '{print $1}' test.txt #显示默认情况下空格隔开的 第一个列

this

[root@mail ~]#

[root@mail ~]# awk '{print $0}' test.txt    #$0 美元符显示所以 即整行文本

this is a test.

[root@mail ~]#


[root@mail ~]# awk '{print $4}' test.txt    #显示默认情况下空格隔开的 第四个列

test.

[root@mail ~]#


[root@mail ~]# awk '{print $1,$2}' test.txt        # 逗号分隔打印,输出时仍然是空白字符分隔

this is

[root@mail ~]#


[root@mail ~]# awk 'BEGIN{OFS="#"}{print $1,$2}' test.txt    #指定输出字符分隔符

this#is

[root@mail ~]#


[root@mail ~]# awk 'BEGIN{OFS=":"}{print $1,$2,$3,$4}' test.txt

this:is:a:test.

[root@mail ~]#


[root@mail ~]# awk 'BEGIN{OFS=":"}{print $1,"hello",$2,$3,$4}' test.txt    # print 补上字符串,用双引号,逗号隔开

this:hello:is:a:test.

[root@mail ~]#


[root@mail ~]# awk '{print "aaaa"}'        #输不出东西


[root@mail ~]# awk 'BEGIN{print "aaaa"}'        #要加BEGIN模式才能输出东西

aaaa

[root@mail ~]#


[root@mail ~]# awk '{print NF}' test.txt    #当前行的字段个数

4

[root@mail ~]#

[root@mail ~]# awk '{print $NF}' test.txt     #当前行的最后一个字段的值

test.

[root@mail ~]#

[root@mail ~]# awk '{print NR}' test.txt        #每一行的行数(第一行为1,第二行为2............)

1

[root@mail ~]#

[root@mail ~]# awk '{print NR}' test.txt health_check.sh    #绝对计数

1

2

3

4

5

6

.

.

.

.


[root@mail ~]# awk '{print FNR}' test.txt health_check.sh    #各自计数 在自己所在的文件计数

1

1

2

3

.

.

.

.


[root@mail ~]# awk 'BEGIN{var="varible testing";print var}'        #在BEGIN模式下,自定义变量

varible testing

[root@mail ~]# awk -v test="hello awk" 'BEGIN{print test}'         # 使用-v 进行自定义变量;; -v (varible)表示 后面跟的是 变量名=变量值 , awk中打印变量值是不需要加美元符 $ 的,这跟bash shell 不一样,加上美元符 $ 就表示打印字段了,那么 test变量此时就是个数字了  ,,,我们只允许它执行一次,后面不带文件,所以要用BEGIN模式

hello awk

[root@mail ~]#

[root@mail ~]# awk 'BEGIN{test="hello awk";print test}';        #action中,语句与语句之间要用分号隔开

hello awk

[root@mail ~]#


[root@mail ~]# awk 'BEGIN{printf "%c","a"}';    #显示ASCII?

a

[root@mail ~]# awk 'BEGIN{printf "%c\n","1"}'

1

[root@mail ~]#

[root@mail ~]# awk '{printf "%c\n",$1}' test.txt

t

[root@mail ~]#

[root@mail ~]# awk '{printf "%s\n",$1}' test.txt    #这里%s表示显示字符串

this

[root@mail ~]# awk '{printf "%10s\n",$1}' test.txt    #10表示宽度 默认右对齐

      this

[root@mail ~]#

[root@mail ~]# awk '{printf "%-10s\n",$1}' test.txt    #左对齐

this

[root@mail ~]#

[root@mail ~]# awk '{printf "%-10s,%-10s\n",$1,$2}' test.txt        #显示两个字符,前面用两个格式分别对应;如果只有一个格式的话,那么就只会显示第一个数据$1

this      ,is        #这里逗号,是格式里面的逗号

[root@mail ~]#


[root@mail ~]# awk '{printf "%-10s%-10s\n",$1,$2}' test.txt    #不想显示逗号,就把格式中的逗号去掉

this      is

[root@mail ~]#



[root@mail ~]# awk -F: '{printf "%5d",$3}' /etc/passwd    #右对齐的

    0    1    2    3    4    5    6    7    8    9   10   11   12   13   14   99   94   28   69   77   38   81   48   70   32   47   51   74   67   16   23   2965534   43   68  100   42   86  500  306   25 2525 2526 2527 2528   97 1001 2529 2530 2531 2532  510 2533 2534 2535 2536


[root@mail ~]# awk -F: '{printf "%5d\n",$3}' /etc/passwd    #换行试试看,清晰的看到右对齐

    0

    1

    2

    3

    4

    5

    6

    7

    8

    9

   10

.

.

.

.


[root@mail ~]# awk -F: '{printf "%-5d\n",$3}' /etc/passwd    #左对齐

0

1

2

3

4

5



[root@mail ~]# awk -F: '/^r/{print $1}' /etc/passwd    #只显示r开头的行的 第一个字段,以冒号为分隔符

root

rpc

rpcuser

redis

redhat

[root@mail ~]#

[root@mail ~]# awk -F: '$3>=500{print $1,$3}' /etc/passwd        #取出uid 大于500的用户

nfsnobody 65534

shipingzhong 500

postfix 2525

postdrop 2526

hadoop 2527

openstack 2528

vmail 1001

hbase 2529

redis 2530

vuser 2531

vsftpd 2532

nfstest 510

eucalyptus 2533

fedora 2534

redhat 2535

test 2536

[root@mail ~]#


[root@mail ~]# awk -F: '$3+1>=500{print $1,$3}' /etc/passwd        # 使用 $3+1>500 也可以

nfsnobody 65534

shipingzhong 500

postfix 2525

postdrop 2526

hadoop 2527

openstack 2528

vmail 1001

hbase 2529

redis 2530

vuser 2531

vsftpd 2532

nfstest 510

eucalyptus 2533

fedora 2534

redhat 2535

test 2536

[root@mail ~]#


[root@mail ~]# awk -F: '$7 ~ "bash$" {print $1,$3}' /etc/passwd    #取出使用 bash 脚本的用户和id,就是看最后一列(第7列)是否匹配bash结尾就可以了

root 0

shipingzhong 500

hadoop 2527

openstack 2528

hbase 2529

redis 2530

nfstest 510

eucalyptus 2533

fedora 2534

redhat 2535

test 2536

[root@mail ~]# 


[root@mail ~]# awk -F: '$7~"bash$"{print $1,$7}' /etc/passwd

root /bin/bash

shipingzhong /bin/bash

hadoop /bin/bash

openstack /bin/bash

hbase /bin/bash

redis /bin/bash

nfstest /bin/bash

eucalyptus /bin/bash

fedora /bin/bash

redhat /bin/bash

test /bin/bash

[root@mail ~]# awk -F:  '$7!~"bash$"{print $1,$7}' /etc/passwd  #取出不使用 bash 脚本的用户和id,就是看最后一列(第7列)是否不匹配bash结尾就可以了

bin /sbin/nologin

daemon /sbin/nologin

adm /sbin/nologin

lp /sbin/nologin

sync /bin/sync

shutdown /sbin/shutdown

halt /sbin/halt

mail /sbin/nologin

news

uucp /sbin/nologin

operator /sbin/nologin

games /sbin/nologin

gopher /sbin/nologin

ftp /sbin/nologin



[root@mail ~]# awk -F: '$3==0,$7~"nologin$"' /etc/passwd        # 匹配第一个 $3=0,第一个$7以nologin$结尾的之间的行

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/sbin/nologin

[root@mail ~]#

[root@mail ~]# awk -F: '$3==0,$7~"nologin$"{print $1,$3,$7}' /etc/passwd    # 匹配第一个 $3=0,第一个$7以nologin$结尾的之间的行,打印出第一列,第三列,第七列

root:x:0:0:root:/root:/bin/bash

root 0 /bin/bash

bin 1 /sbin/nologin

[root@mail ~]#


[root@mail ~]# awk -F: '$3==0,$7~"nologin$"{printf "%-10s%-10s%-20s\n", $1,$3,$7}' /etc/passwd        #10个字符左对齐,再10个字符左对齐,再20个字符左对齐,

root      0         /bin/bash

bin       1         /sbin/nologin

[root@mail ~]#

[root@mail ~]# awk -F: 'BEGIN{print "Username    ID    Shell"}{printf "%-10s%-10s%-20s\n",$1,$3,$7}' /etc/passwd        #打出头部  (仅打印一次)

Username    ID    Shell

root      0         /bin/bash

bin       1         /sbin/nologin

daemon    2         /sbin/nologin

adm       3         /sbin/nologin

lp        4         /sbin/nologin

.

.

.

.

[root@mail ~]# awk -F: 'BEGIN{print "Username    ID    Shell"}{printf "%-10s%-10s%-20s\n",$1,$3,$7}END{print "End    of  report"}' /etc/passwd        #打出头部和尾部  (仅打印一次)

Username    ID    Shell

root      0         /bin/bash

bin       1         /sbin/nologin

daemon    2         /sbin/nologin

adm       3         /sbin/nologin

lp        4         /sbin/nologin

.

.

.

.

End    of  report


[root@mail ~]# awk -F: '{printf "%-10s%-10s%-20s\n",$1,$3,$7}' /etc/passwd      #空模式,没有模式,处理的是所有的行

root      0         /bin/bash

bin       1         /sbin/nologin

daemon    2         /sbin/nologin

adm       3         /sbin/nologin

.

.

.

.

[root@mail ~]# awk -F: '{if ($1=="root") print $1, "Admin"; else print $1, "Common User"}' /etc/passwd

root Admin

bin Common User

daemon Common User

adm Common User

.

.

.

.


[root@mail ~]# awk -F: '{if ($1=="root") printf  "%-15s:  %s\n", $1,"Admin"; else printf  "%-15s:  %s\n",$1,"Common User"}' /etc/passwd        #与上一个命令的不同,就是进行了格式化 "%-15s:  %s\n" 表示第一个字符串左对齐,15个字符,第二个字符串是字符

root           :  Admin

bin            :  Common User

daemon         :  Common User

.

.

.

.

[root@mail ~]# awk -F: -v sum=0 '{if ($3>=500) sum++}END{print sum}' /etc/passwd                   #id大于等于500的所有用户的个数

 16

[root@mail ~]#

 

[root@mail ~]# awk -F:  '{i=1;while (i<=NF){ if (length($i)>=4) print $i;i++ }}'  /etc/passwd        #每一行的字段中;字符长度大于等于4的才显示出来,,,while循环的并不是行,而是行中的字段

root

root

/root

/bin/bash

/bin

/sbin/nologin

.

.

.

.


[root@mail ~]# df -hP

文件系统              容量  已用 可用 已用% 挂载点

/dev/mapper/VolGroup00-LogVol00   18G  6.8G  9.7G  42% /

/dev/sda1              99M   13M   82M  13% /boot

tmpfs                 506M     0  506M   0% /dev/shm

/dev/mapper/myvg-mydata2  194M   47M  137M  26% /mydata2

[root@mail ~]# 


[root@mail ~]# awk -F: '{for(i=1;i<=NF;i++){if(length($i)>=4) print $i }}' /etc/passwd         #每一行的字段中;字符长度大于等于4的才显示出来,,,for循环的并不是行,而是行中的字段

root

root

/root

/bin/bash

.

.

.

.

image.png


[root@mail ~]# awk -F: '{shell[$NF]++}END{for(A in shell){print A,shell[A]}}' /etc/passwd  # 这里A是数组的下标,不是值,与js 一样;;;;;  这个语句的结果是打印每个shell,及使用的各个shell的个数

 1

/bin/sync 1

/bin/bash 11

/sbin/login 1

/sbin/nologin 40

/sbin/halt 1

/sbin/shutdown 1

[root@mail ~]#


  awk中,变量的初始值为0,所以 shell[$NF]初始值为0

shell[/bin/bash]++

shell[/bin/nologin]++



[root@mail ~]# netstat -tan        #显示当前的已建立的连接或监听连接的每一个tcp连接的连接状态

Active Internet connections (servers and established)

Proto Recv-Q Send-Q Local Address               Foreign Address             State

tcp        0      0 127.0.0.1:2208              0.0.0.0:*                   LISTEN

tcp        0      0 0.0.0.0:2049                0.0.0.0:*                   LISTEN

tcp        0      0 0.0.0.0:32803               0.0.0.0:*                   LISTEN

tcp        0      0 0.0.0.0:901                 0.0.0.0:*                   LISTEN

tcp        0      0 127.0.0.1:9000              0.0.0.0:*                   LISTEN

tcp        0      0 0.0.0.0:3306                0.0.0.0:*                   LISTEN

tcp        0      0 0.0.0.0:875                 0.0.0.0:*                   LISTEN

tcp        0      0 0.0.0.0:716                 0.0.0.0:*                   LISTEN

tcp        0      0 0.0.0.0:111                 0.0.0.0:*                   LISTEN

tcp        0      0 192.168.0.77:53             0.0.0.0:*                   LISTEN

tcp        0      0 0.0.0.0:21                  0.0.0.0:*                   LISTEN

tcp        0      0 192.168.0.75:53             0.0.0.0:*                   LISTEN

tcp        0      0 127.0.0.1:53                0.0.0.0:*                   LISTEN

tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN

tcp        0      0 0.0.0.0:23                  0.0.0.0:*                   LISTEN

tcp        0      0 127.0.0.1:631               0.0.0.0:*                   LISTEN

tcp        0      0 0.0.0.0:25                  0.0.0.0:*                   LISTEN

tcp        0      0 127.0.0.1:953               0.0.0.0:*                   LISTEN

tcp        0      0 0.0.0.0:892                 0.0.0.0:*                   LISTEN

tcp        0      0 127.0.0.1:2207              0.0.0.0:*                   LISTEN

tcp        0    264 192.168.0.75:22             192.168.0.103:10760         ESTABLISHED

tcp        0      0 :::995                      :::*                        LISTEN

tcp        0      0 :::110                      :::*                        LISTEN

tcp        0      0 :::80                       :::*                        LISTEN

tcp        0      0 :::22                       :::*                        LISTEN

tcp        0      0 ::1:953                     :::*                        LISTEN


[root@mail ~]#

[root@mail ~]# netstat -tan | awk '/^tcp/{STATE[$NF]++}END{for(S in STATE) print S,STATE[S]}'  #统计netstat -tan   每一种状态出现的次数  找到以tcp开头的行  $NF是最后一个字段的值,S是下标,指的就是最后一个字段的值,STATE是数组, STATE[S]指的是每一种状态的次数

LISTEN 25

ESTABLISHED 1

[root@mail ~]#


[root@mail ~]#  awk '{count[$1]++}END{for(ip in count){printf "%20s:%d\n",ip,count[ip]}}' /usr/local/apache/logs/access_log        #在access_log文件中 第一个字段(不同的客户端的ip)出现的次数,然后打印出 ip 及次数

       192.168.1.251:479

[root@mail ~]#


普通分类: