awk 笔记

Table of Contents

1 awk 匹配模式

语法:

  匹配 {动作}
{
    BEGIN {print "hello world"}
}

# 整行匹配
{
    /root/ {print $0}
}

1.1 正则

1.1.1 提取正则匹配的结果

echo abc123 | awk 'match($1, /[0-9]+/, a){print a[0]}

2 变量定义

2.1 内置变量

FNR,当前文件的所在行。例,打印某一样的数据:

awk -F: 'FNR == 3{print}' /etc/passwd

NR:记录当前共读了多少行。

FNR 和 NR 在多文件情况下能区别出来:

awk '{print FNR}' /etc/passwd /etc/hosts
awk '{print NR}' /etc/passwd /etc/hosts

NF,当前行的列数。例,找出少于 4 列的行:

{print NF}

例,打印最后一列:

{print $NF}

例,行列互换,member.txt 内容如下:

name lx
blog www.shellcodes.org
github http://github.com/1u4nx

将它转为如下格式:

name blog github
lx www.shellcodes.org http://github.com/1u4nx

实现代码如下:

{
    for (i=1; i<=NF; i++) {
        data[i, NR] = $i
    }
}

END {
    for (i=1; i<=NF; i++) {
        for(n=1; n<=NR; n++) {
            printf data[i, n] " "
        }
        print ""
    }
}

2.2 和 shell 交互

例,正则使用 shell 中的变量

for i in {00..05}
do
    awk '$2~/2016-04-07<SP>'$i'/' web.log
done

3 列操作

3.1 列引用

for (i=0; i<3; i++) {
    print $(i) # 引用第 i 列的数据
}

3.2 排除某列

例,打印数据,并排除第一列:

{
    $1=null;
    print
}

4 数组

遍历数组方法1:

awk -F: '{users[FNR]=$1};END{len=length(users);for (i=0;i<=len;i++) {print users[i]}}' /etc/passwd

遍历数组方法2:

awk -F: '{users[$1]=1};END{for (user in users) {print user}}' /etc/passwd

例,有一个日志文件,还有一个 IP 列表文件,需要从日志中按 IP 列表导出相应的日志:

BEGIN {
    while (getline < "IP列表.txt") {
        ips[$0]=1;
    }

    while (getline < "日志文件") {
        split($0, ft, " ");
        if(ips[ft[6]]) {
            print $0;
        }
    }
}

去重:

awk '!x[$0]++' 文件名

5 其他

调用外部命令结果作为输出:

awk '{if(NF==2){cmd="python ipip.py " $1; cmd | getline result; close(cmd);print $1,$2,result}else{print $0}}' xx > result.txt