我们把这门_语言_称为AWK,把解释 AWK 程序的_可执行文件_称为**awk或gawk**。
一个 AWK 程序由模式-动作对组成
pattern1 { action1 }
pattern2 { action2 }
...
模式可以是用来匹配输入的正则表达式,也可以是任何结果为 true/false 的表达式。
动作是一条或多条 AWK 命令。外面的大括号是必需的。
如果模式的结果为 true,就会执行与之对应的动作。
AWK 把输入解析成一系列记录。每条记录又被拆分成零个或多个字段。
默认行为是:
模式可以省略,这时动作会_针对每一条输入记录_执行。
动作也可以省略,这时默认的动作就是打印当前记录。
有两个常用的特殊模式。
BEGIN会在读取任何输入之前执行与之关联的动作。END会在所有输入读取完毕之后执行与之关联的动作。可以用$1、$2、$3等来引用字段。
当前记录是$0。
说得明确一些,它们严格来说并不是“变量”。
$可以看作一个_运算符_,用来取得给定字段编号的值。
我们会在后面的概念里深入讨论这一点。
下面还有一些其他常用的内置变量。
RS是输入记录分隔符。
如前所述,它的默认值是换行符。FS是输入字段分隔符。这些变量通常在BEGIN动作块中设置。
这些变量由 AWK 在程序执行过程中自动设置。
NF保存当前记录中的字段数。
$NF。NR保存当前的记录编号。
NR会保存到目前为止处理过的记录总数。FNR保存当前输入文件中的当前记录编号。
NR == FNR {action}
它的意思是“如果累计的记录编号等于当前文件的记录编号”。
只有_第一个输入文件_中的记录才可能满足这个条件。AWK 使用的真值性概念与 C 相同:
0为 false。由于 AWK 是一门文本处理语言,真值也扩展到了字符串。
""为 false。AWK 使用的真值性概念与 C 相同
AWK 于 20 世纪 70 年代诞生于贝尔实验室,那里的环境也正是 C 诞生的地方。 C 对 AWK 的语法有很大影响。
有一个需要留意的奇怪之处
0为 false。"0"却为 true!我们会在后面的概念里进一步讨论 AWK 的数据类型。
注释以#字符开头,一直延伸到行尾。
awk提供输入awk可以从文件或标准输入中读取输入。下面这些方法都可以用。
awk '/regex/ {print $1}' file1 file2 ...
awk '/regex/ {print $1}' < file
some_command_here | awk '/regex/ {print $1}'
在类 Unix 系统上,/etc/passwd保存着用户信息。每个用户占一行,字段之间用冒号分隔。
要列出所有用户名:
awk '
BEGIN { FS = ":" }
{ print $1 }
' /etc/passwd
注意,{print $1}这个动作没有模式,所以每条记录都会执行它。
如果我们只想输出登录 shell 为 bash 的用户,可以这样做:
awk '
BEGIN { FS = ":" }
$7 == "/bin/bash" { print $1 }
' /etc/passwd
下面是一些 awk 程序,它们能产生与其他常见 Unix 命令相同的效果。
显示文件
cat file.txt
awk '1' file.txt
在文件中搜索模式
grep 'foo.*bar' file.txt
awk '/foo.*bar/' file.txt
只显示文件开头的几行
head -n 20 file.txt
awk '
1
NR == 20 {exit}
' file.txt
替换文件中的文本
sed 's/foo/bar/' file.txt
awk '{sub(/foo/, "bar")};1' file.txt
# or more readably
awk '
{
sub(/foo/, "bar")
print
}
' file.txt