跳转到内容

Unix 指南/解释/awk

来自维基教科书,开放的书籍,为开放的世界

名称 'awk' 来自三位最初开发它的人的名字 - Aho、Weinberger 和 Kernighan。它是一种编程语言,使用模式-动作表达式将输入转换为输出。它处理输入(通常是数据文件),在每行中搜索给定的模式。任何与给定模式匹配的行都会应用动作,并且这构成了输出。不匹配的行将被忽略。

每个输入行都由分隔符字符(默认是空格)划分为字段,并且模式可以与这些字段匹配,因为它们以通常的 Unix 样式引用 - $1 是字段 1,$2 是字段 2 等。$0 表示整个输入行。

如果没有指定模式,则选择所有输入行。如果没有指定动作,则默认动作是打印整行。因此,如果您只想打印输入的子集,您只需要提供一个将产生所需结果的模式,Awk 将按原样打印输入。

但是,您也可以以相同的方式指定要输出的字段,例如 print $1。

一个简单的例子

awk '$1 ~ /A/ { print $2 " " $3 }' /etc/passwd

程序结构

[编辑 | 编辑源代码]

awk 程序由一个或多个模式-动作语句组成

pattern   { action }
pattern   { action }
 :
 :

awk 扫描数据输入行,并对与任何指定模式匹配的这些行执行操作。


运行 AWK

[编辑 | 编辑源代码]

在这里,我们从一个 shell 脚本 awk1.sh 中调用 awk

#!/bin/bash

# awk1.sh
awk '
       { print }
' $1

没有模式,因此馈送到 awk 的每一行都匹配,并且会调用动作。这会导致文件的每一行都打印到屏幕上。因此,awk1.sh 的行为类似于 cat

为了演示,创建文件 numeric.dat,其内容为

1 one   i
2 two   ii
3 three iii
4 four  iv
5 five  v
6 six   vi
7 seven vii
8 eight viii
9 nine  ix
10 ten  x

numeric.dat 上运行 awk1.sh(不要忘记使脚本可执行)

./awk1.sh numeric.dat
1 one   i
2 two   ii
3 three iii
4 four  iv
5 five  v
6 six   vi
7 seven vii
8 eight viii
9 nine  ix
10 ten  x

(注意如何使用    ./    执行脚本。)

表达式 =

[编辑 | 编辑源代码]

如果第一个字段等于 1,则打印整行

#!/bin/sh
# awk1.sh
awk '
    $1 == 1 { print $0 }
' $1

结果为

1 one i

如果第二个字段等于 "two",则打印整行

$2 == "two" { print $0 }

结果为

2 two ii

如果第一个字段大于 5,则打印第三个字段

$1 > 5 { print $3 }

结果为

 vi
 vii
 viii
 ix
 x

正则表达式

[编辑 | 编辑源代码]

如果模式 "ix" 在任何字段中匹配,则打印输入行

/ix/ { print $0 } 

结果为

6 six   vi
9 nine  ix

如果模式 "ix" 在第三个字段中匹配,则打印输入行

$3 ~ /ix/ { print $0 } 

结果为

9 nine  ix

打印不包含模式 "x" 的输入行

$0 !~ /x/ { print }

结果为

1 one   i
2 two   ii
3 three iii
4 four  iv
5 five  v
7 seven vii
8 eight viii

复合表达式

[编辑 | 编辑源代码]

打印第三个字段与模式 "x" 匹配或第一个字段小于或等于 3 的行。

$3 ~ /x/ ||  $1 <= 3  { print $0 }

结果为

1 one   i
2 two   ii
3 three iii
9 nine  ix
10 ten  x

打印第三个字段与模式 "vi" 匹配且第二个字段以字母 "s" 开头的行。

$3 ~ /vi/ && $2 ~ "^s"  { print $0 }

结果为

6 six   vi
7 seven vii

打印第二个字段等于 "three" 且第三个字段等于 "vii" 以及所有后续行之间的行

$2 == "three", $3 == "vii" { print $0 }

结果为

3 three iii
4 four  iv
5 five  v
6 six   vi
7 seven vii

BEGIN 和 END

[编辑 | 编辑源代码]

BEGIN 是一种特殊模式,它在第一行输入之前匹配。类似地,END 在最后一行输入之后匹配。

BEGIN { print "start at 3..." }
$2 == "three", $2 ~ /^e/ { print $1 }
END { print "...and end at eight" }

结果为

start at 3...
3 
4 
5 
6 
7 
8 
...and end at eight
华夏公益教科书