以这种方式调用 print 时,它将连接 $1、" " 和 $3,创建可读的输出 。当然,如果需要的话,我们还可以插入一些文本标签:
$ awk -F":" "{ print "username: " $1 "ttuid:" $3" }" /etc/passwd
这将产生以下输出:
username: halt uid:7username: operator uid:11username: root uid:0username: shutdown uid:6username: sync uid:5username: bin uid:1....etc.
外部脚本
将脚本作为命令行自变量传递给 awk 对于小的单行程序来说是非常简单的,而对于多行程序,它就比较复杂 。您肯定想要在外部文件中撰写脚本 。然后可以向 awk 传递 -f 选项,以向它提供此脚本文件:
$ awk -f myscript.awk myfile.in
将脚本放入文本文件还可以让您使用附加 awk 功能 。例如,这个多行脚本与前面的单行脚本的作用相同,它们都打印出 /etc/passwd 中每一行的第一个字段:
BEGIN { FS=":"}{ print $1 }
这两个方法的差别在于如何设置字段分隔符 。在这个脚本中,字段分隔符在代码自身中指定(通过设置 FS 变量),而在前一个示例中,通过在命令行上向 awk 传递 -F":" 选项来设置 FS 。通常,最好在脚本自身中设置字段分隔符,只是因为这表示您可以少输入一个命令行自变量 。我们将在本文的后面详细讨论 FS 变量 。
BEGIN 和 END 块
通常,对于每个输入行,awk 都会执行每个脚本代码块一次 。然而,在许多编程情况中,可能需要在 awk 开始处理输入文件中的文本之前执行初始化代码 。对于这种情况,awk 允许您定义一个 BEGIN 块 。我们在前一个示例中使用了 BEGIN 块 。因为 awk 在开始处理输入文件之前会执行 BEGIN 块,因此它是初始化 FS(字段分隔符)变量、打印页眉或初始化其它在程序中以后会引用的全局变量的极佳位置 。
awk 还提供了另一个特殊块,叫作 END 块 。awk 在处理了输入文件中的所有行之后执行这个块 。通常,END 块用于执行最终计算或打印应该出现在输出流结尾的摘要信息 。
规则表达式和块
awk 允许使用规则表达式,根据规则表达式是否匹配当前行来选择执行独立代码块 。以下示例脚本只输出包含字符序列 foo 的那些行:
/foo/ { print }
当然,可以使用更复杂的规则表达式 。以下脚本将只打印包含浮点数的行:
/[0-9] .[0-9]*/ { print }
表达式和块
还有许多其它方法可以选择执行代码块 。我们可以将任意一种布尔表达式放在一个代码块之前,以控制何时执行某特定块 。仅当对前面的布尔表达式求值为真时,awk 才执行代码块 。以下示例脚本输出将输出其第一个字段等于 fred 的所有行中的第三个字段 。如果当前行的第一个字段不等于 fred,awk 将继续处理文件而不对当前行执行 print 语句:
$1 == "fred" { print $3 }
awk 提供了完整的比较运算符集合,包括 "=="、"<"、">"、"<="、">=" 和 "!=" 。另外,awk 还提供了 "~" 和 "!~" 运算符,它们分别表示“匹配”和“不匹配” 。它们的用法是在运算符左边指定变量,在右边指定规则表达式 。如果某一行的第五个字段包含字符序列 root,那么以下示例将只打印这一行中的第三个字段:
$5 ~ /root/ { print $3 }
条件语句
awk 还提供了非常好的类似于 C 语言的 if 语句 。如果您愿意,可以使用 if 语句重写前一个脚本:
{ if ( $5 ~ /root/ ) { print $3 }}
这两个脚本的功能完全一样 。第一个示例中,布尔表达式放在代码块外面 。而在第二个示例中,将对每一个输入行执行代码块,而且我们使用 if 语句来选择执行 print 命令 。这两个方法都可以使用,可以选择最适合脚本其它部分的一种方法 。
以下是更复杂的 awk if 语句示例 。可以看到,尽管使用了复杂、嵌套的条件语句,if 语句看上去仍与相应的 C 语言 if 语句一样:
推荐阅读
- 通用线程--sed 实例,第3部分
- 通用线程--sed 实例,第1部分
- 通用线程--sed 实例,第2部分
- FreeBSD下设置modem和modem的通用命令
- 什么叫多线程
- 和彩云支持普通用户上传多大文件
- 缝好衣服后怎么用短线快速打结?男女通用
- 医保是全国通用的吗
- 5e和steam皮肤通用吗
- 下 Solaris 10通用桌面CDE快速入门