Awk学习_6


=Start=

0.awk的程序设计模型

awk程序是由所谓的主输入(main input)循环组成的。一个循环是一个例程,它将一直重复执行直到由一些存在的条件终止它。你不必写这个循环,它是现成的,它作为一个框架存在,在这个框架中你编写的代码能够执行。

awk允许你编写两个特殊的例程,它们在任何输入被读取前所有输入都被读取后执行。它们是与BEGIN和END规则相关的过程。

1.awk的split/substr/index函数的使用
# 使用split返回字符串数组元素个数。
awk 'BEGIN {print split("123#456#678", myarray, "#")}'  # 3

netstat -lntp | awk 'NR>2 {a_len=split($4,a,":"); print a_len, a[a_len]}'
netstat -lntp | awk 'NR>2 {a_len=split($4,a,":"); print $4, a[a_len]}'
netstat -lntp | awk 'NR>2 {b_len=split($NF,b,"/"); print b_len, b[b_len]}'
netstat -lntp | awk 'NR>2 {b_len=split($NF,b,"/"); print $NF, b[b_len]}'


/sbin/ip a l | grep "inet " | grep -v '127.0.0' | awk '{print $2}'
/sbin/ip a l | grep 'inet ' | grep -v '127.0.0' | awk '{print $2}' | xargs | tr ' ' '|'

/sbin/ifconfig | grep "inet " | grep -v '127.0.0' | awk '{split($2, a, ":"); print a[2]}'
/sbin/ifconfig | grep 'inet ' | grep -v '127.0.0' | awk '{split($2, a, ":"); print a[2]}' | xargs | tr ' ' '|'

# awk的 split 函数无法指定切分的次数,所以在碰到下面的那种启动进程的方式时就容易有问题
# # netstat -lntp
# Active Internet connections (only servers)
# Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name
# tcp        0      0 0.0.0.0:7710                0.0.0.0:*                   LISTEN      1270/./redis-3.0.0/
# tcp        0      0 0.0.0.0:7712                0.0.0.0:*                   LISTEN      1271/./redis-2.8.23

## 使用 index 和 substr 达到类似的功能 ##
# netstat -lntp | awk 'NR>2 {pos=index($NF, "/"); print $NF, pos}'
1309/mysqld 5
10790/./redis-3.0.5 6
1195/sshd 5
1380/master 5
10790/./redis-3.0.5 6
1195/sshd 5

# netstat -lntp | awk 'NR>2 {pos=index($NF, "/"); print substr($NF, pos)}'
/mysqld
/./redis-3.0.5
/sshd
/master
/./redis-3.0.5
/sshd

# netstat -lntp | awk 'NR>2 {pos=index($NF, "/"); print substr($NF, pos+1)}'   #可以直接使用'+'进行算术操作
mysqld
./redis-3.0.5
sshd
master
./redis-3.0.5
sshd
2.awk的next的使用
#示例:解析XML文件(过滤掉空行和注释行)
$ cat "$file" | awk '/<!--/,/-->/{next}1' | tr -d '\n\r' | sed 's/>/>\n/g' | tr '\t' ' ' | tr -s ' ' | sed 's/^ //g;s/ $//g' | grep -v '^$'
3.用awk处理多行记录
#为了处理以下这种包含多行数据的记录,我们可以将字段分隔符(FS)定义为换行符,并将记录分隔符(RS)设置为空字符串——它代表一个空行。
$ cat ./multi_line_record.txt
John Daggett
Koren Inc.
341 King Road
Plymouth
MA 01760
696-0987

Alice Ford
Meituan Inc.
22 East Broadway
Richmond
VA 08239
699-1998

$ awk 'BEGIN{ FS = "\n"; RS = "" } { print $1, $NF }' multi_line_record.txt
John Daggett 696-0987
Alice Ford 699-1998

 

注意:

在命令行中使用awk时,必须有

  • 单引号
  • 大括号
参考链接:

=EOF=

, ,

《“Awk学习_6”》 有 6 条评论

  1. “`
    ##awk复杂分隔符##
    多字符作分隔符
    $ echo “a||b||c||d” | awk -F ‘[|][|]’ ‘{print $3}’
    c
    多种分隔符1
    $echo “a||b,#c d” | awk -F ‘[| ,#]+’ ‘{print $4}’
    d
    多种分隔符2
    $echo “a||b##c|#d” | awk -F ‘([|][|])|([#][#])’ ‘{print $NF}’
    c|#d
    “`

  2. awk中的FieldSeparator可以是由多字符组成的,比如:
    “`
    $ echo ‘”School”,”College”,”City”‘ | awk -F’”,”|^”|”$’ ‘{for(i=1;i<=NF;i++){if($i)print $i}}'
    School
    College
    City
    “`
    如果你希望awk按普通字符解释「管道字符——'|'」,你需要用下面的方法:
    “`
    $ echo "a|b|c|d" | awk -F '[|]' '{print $3}'
    “`

  3. awk拆分文件很简单,使用重定向就好了。下面这个例子,是按第6例分隔文件,相当的简单(其中的NR!=1表示不处理表头)。
    `
    $ cat netstat.txt
    Proto Recv-Q Send-Q Local-Address Foreign-Address State
    tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
    tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN
    tcp 0 0 coolshell.cn:80 124.205.5.146:18245 TIME_WAIT
    tcp 0 0 coolshell.cn:80 61.140.101.185:37538 FIN_WAIT2
    tcp 0 0 coolshell.cn:80 110.194.134.189:1032 ESTABLISHED

    $ awk ‘NR!=1{print > $6}’ netstat.txt
    $ ls
    ESTABLISHED FIN_WAIT2 LISTEN netstat.txt TIME_WAIT
    `

    你也可以把指定的列输出到文件:
    `$ awk ‘NR!=1{print $4,$5 > $6}’ netstat.txt
    `

    再复杂一点:(注意其中的if-else-if语句,可见awk其实是个脚本解释器)
    `
    $ awk ‘NR!=1{if($6 ~ /TIME|ESTABLISHED/) print > “1.txt”;
    else if($6 ~ /LISTEN/) print > “2.txt”;
    else print > “3.txt” }’ netstat.txt
    `

    AWK 简明教程
    http://coolshell.cn/articles/9070.html

  4. Linux之awk内建数学函数之左移运算、右移运算、按位取反运算
    https://www.dwhd.org/20150917_013542.html

    Linux之awk中 !a[$0]++ 与 !a[$1…]++ [转载自苦海无边博客]
    https://www.dwhd.org/20150917_020937.html

    Linux之awk实现ip地址转二进制和数字模式&十进制转二进制
    http://www.dwhd.org/20150910_011543.html

    Linux之awk实现ls -l输出文件权限的数字&打造加强版的ls命令
    http://www.dwhd.org/20150909_020139.html

  5. 当使用awk的多分隔符进行字符串切分的时候,要注意下面这种使用方式需要对【.】进行转义才行
    `
    cat enterprise-ssid.txt| sort | uniq | awk -F’ |-|_|\\.’ ‘NF>1 {print tolower($2)}’ | sort | uniq -c | sort -rn
    `

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注