awk 笔记

一、准备工作

在当前文件夹创建employee.txt文件,作为数据来源

1. employee.txt

01 ian 20000
02 alex 30000
03 lex 15000
04 ash 43000
05 bob 21000
06 faker 20000
07 boss 99999

二、一个简单的例子

打印第二列的数据

awk '{print $2}' employee.txt

# boss
# lex
# ian
# alex
# van
# bob
# john
# levin
# ash

或者是通过读取流的方式

cat employee.txt | awk '{print $2}'

# boss
# lex
# ian
# alex
# van
# bob
# john
# levin
# ash

除了读取文件以外,一般都是通过第二种,即读取流的方式,因为*nix中流更常见

注意awk '{print $2}'中的单引号不要打成了双引号

对整个语句进行拆分:

  • awk: 命令名称
  • '{print $2}': 单引号包着的部分可以理解为awk语言的代码(awk实际上是一门编程语言)。awk是按行执行的,每到一行就会执行{}里边的代码。print $2,表示打印当前行的第二列,所以整个语句{print $2}表示打印每一行的第二列,所以最终结果就是只把第二列打印了出来。

三、将awk代码放入文件中

除了上面的命令行模式外,awk还支持从文件中读取处理的代码

  1. 创建format文件,内容如下
{
    print 2
}

# 写成单行的 {print2} 也行
  1. 执行命令
awk -f format employee.txt

# boss
# lex
# ian
# alex
# van
# bob
# john
# levin
# ash

四、还可以写成shebang风格的脚本

  1. 创建format.awk文件,内容如下
#! /usr/bin/awk -f
{
    print $2
}
  1. format.awk可执行权限
chmod a+x format.awk
  1. 执行
./format.awk employee.txt

# boss
# lex
# ian
# alex
# van
# bob
# john
# levin
# ash

五、打印出所有数据(但是没有实际意义)

print无参数打印每一行的所有列

awk '{print}' employee.txt

# 01 ian 20000
# 02 alex 30000
# 03 lex 15000
# 04 ash 43000
# 05 bob 21000
# 06 faker 20000
# 07 boss 99999

$0为整行

awk '{print $0}' employee.txt

# 01 ian 20000
# 02 alex 30000
# 03 lex 15000
# 04 ash 43000
# 05 bob 21000
# 06 faker 20000
# 07 boss 99999

使用后面将会讲到的正则,不给予匹配条件

awk '//' employee.txt

三、打印第一列和第三列

awk '{print 1,3}' employee.txt

四、格式化打印

awk '{printf "%d %-8s %-8d\n", 1,2, $3}' employee.txt

# 1 ian      20000
# 2 alex     30000
# 3 lex      15000
# 4 ash      43000
# 5 bob      21000
# 6 faker    20000
# 7 boss     99999

五、使用BEGIN增加表头

BEGIN{}里边放的内容只会在开始前执行一次,所以可以用来输出表头之类的数据

1. format.awk
#! /usr/bin/awk -f

BEGIN{ printf "%-2s %-8s %-8s\n", "id", "name", "salary" }

{ printf "%-2d %-8s %-8sn", 1,2, $3 }

2. 执行 ./format.awk employee.txt
$ ./format.awk employee.txt

# id name     salary
# 1  ian      20000
# 2  alex     30000
# 3  lex      15000
# 4  ash      43000
# 5  bob      21000
# 6  faker    20000
# 7  boss    99999

六. 汇总 (END)

END{}里边的代码只会在最后一行处理完后执行

1. format.awk

#! /usr/bin/awk -f

BEGIN{ printf "%-2s %-8s %-8s\n", "id", "name", "salary" }

{ printf "%-2s %-8s %-8s\n", 1,2, 3, total_salary +=3 }

END{ printf "total salary is %.2f", total_salary }

2. 执行 ./format.awk employee.txt

$ ./format.awk employee.txt

# id name     salary
# 01 ian        20000
# 02 alex      30000
# 03 lex        15000
# 04 ash       43000
# 05 bob       21000
# 06 faker     20000
# 07 boss     99999
# total salary is 248999.00%

七、打印行号

awk '{print NR, $0}'

# 1 01 ian 20000
# 2 02 alex 30000
# 3 03 lex 15000
# 4 04 ash 43000
# 5 05 bob 21000
# 6 06 faker 20000
# 7 07 boss 99999

八、打印每一行有多少列

awk '{print NF, $0}'

# 3 01 ian 20000
# 3 02 alex 30000
# 3 03 lex 15000
# 3 04 ash 43000
# 3 05 bob 21000
# 3 06 faker 20000
# 3 07 boss 99999

九、条件打印

1. 打印第一行

awk 'NR == 1 {print}' employee.txt

# 01 ian 20000

2. 打印薪资(第三列)大于 30000 的行

awk '$3 > 30000 {print}' employee.txt

# 04 ash 43000
# 07 boss 99999

3. 打印第 2 列中字符长度大于 3 的行

awk 'length($2) > 3' employee.txt

# 02 alex 30000
# 06 faker 20000
# 07 boss 99999

4. 打印除了第一行的所有行

awk 'NR > 1 {print}' employee.txt

# 02 alex 30000
# 03 lex 15000
# 04 ash 43000
# 05 bob 21000
# 06 faker 20000
# 07 boss 99999

5. 打印第一行和第三行

awk 'NR == 1 || NR == 3 {print}' employee.txt

# 01 ian 20000
# 03 lex 15000

6. 打印最后一行

$0 在END块中已经获取不到了,所以要在之前保存下来

awk '{last = $0} END{print last}' employee.txt

十、传递变量

awk -v name=ian '$2 == name {print}' employee.txt

# 01 ian 20000

十一、查找

1. 查找所有列中包含 2 的记录

awk '/2/' employee.txt

# 01 ian 20000
# 02 alex 30000
# 05 bob 21000
# 06 faker 20000

上面例子相当于 awk '/2/ {print} employee.txt'

2. 查找第三列中包含 2 的记录

awk '$3 ~ /2/' employee.txt

# 01 ian 20000
# 05 bob 21000
# 06 faker 20000

3. 查找第三列中不包含 2 的记录

awk '$3 !~ /2/' employee.txt

# 02 alex 30000
# 03 lex 15000
# 04 ash 43000
# 07 boss 99999

4. 查找第二列中 a 开头的记录

awk '$2 ~ /^a/' employee.txt

# 02 alex 30000
# 04 ash 43000

5. 查找第二列中 x 结尾的记录

awk '2 ~ /x/' employee.txt

# 02 alex 30000
# 03 lex 15000

6. 查找第二列中包含 lex 或 ian 的行

awk '/lex|ian/' employee.txt

# 01 ian 20000
# 02 alex 30000
# 03 lex 15000

7. 查找第二列中不是 a 开头并包含 lex 的行

awk '/[^a]lex/' employee.txt

# 03 lex 15000

十二、数组

1. 基本使用

awk 'BEGIN{
    arr["first"] = "apple"
    arr["second"]="orange"
    print arr["first"]
    print arr["second"]
}'

# apple
# orange

2. 删除一个元素

awk 'BEGIN{
    arr["first"] = "apple"
    arr["second"] = "orange"
    arr["third"] = "fruit"
    delete arr["third"]
    print arr["first"]
    print arr["second"]
}'

# apple
# orange
#

流程语句

awk '{
    if( 3>25000 ){
        print0
    }
    else{
        print "-------------"
    }
}' employee.txt

# -------------
# 02 alex 30000
# -------------
# 04 ash 43000
# -------------
# -------------
# 07 boss 99999
awk '{
   if( 3<20000 ){
     print "low"
   }   else if(3 >= 20000 && $3 < 30000 ){
     print "normal"
   }
   else{
     print "high"
   }
 }' employee.txt

# normal
# high
# low
# high
# normal
# normal
# high

内置函数

1. 字符串替换 gsub

有一天,boss 说 ian 不用干了,所以工资又回到 boss 手中

awk '{gsub("ian", "boss", $2)} {print}' employee.txt


# 01 boss 20000
# 02 alex 30000
# 03 lex 15000
# 04 ash 43000
# 05 bob 21000
# 06 faker 20000
# 07 boss 99999

参考

AWK 简明教程 - 酷 壳 – CoolShell
AWK程序设计语言

点赞

发表评论

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