shell脚本编程之awk

下面是第一条awk命令
awk '{ print }' /etc/passwd
执行 awk 时,它依次对 /etc/passwd 中的每一行执行 print 命令。所有输出都发送到 stdout。在shell下执行会把文件内容全部打印出来,等价于命令"cat /etc/passwd"。
在 awk 中,花括号用于将几块代码组合到一起,这一点类似于 C 语言。花括号里面的代码会在后面文件的每一行内容输入进来执行一遍。上面例子中花括号内只有print以行执行代码,他会把文件每一行内容都打印出来。此处也可以有其他代码,也可以和输入进来的行无关。比如:
awk '{ print "hello" }' /etc/passwd
此时会打印文件行数个hello。

awk 非常善于处理分成多个逻辑字段的文本,而且让您可以毫不费力地引用 awk 脚本中每个独立的字段。
在调用 awk 时,使用 -F 选项来指定 ":" 作为字段分隔符。awk 处理 print $1 命令时,它会打印出在输入文件中每一行中出现的第一个以“:”分隔的字段。
awk -F":" '{ print $1 $3 }' /etc/passwd
上面命令打印第1,3个字段,但是是连接在一起的,我们可以加入一些分割字符,打印出可读字符串。如下:
awk -F":" '{ print "name: " $1"\t\tuid:" $3}' /etc/passwd


将脚本放入文本文件还可以让您使用附加 awk 功能。
BEGIN {

                FS=":"

}

{ print $1 }

将上面脚本放入脚本保存为my.awk中,然后在shell命令下执行
awk -f my.awk /etc/passwd
会出现和命令:awk '{ print $1}' /etc/passwd一样的结果。

通常,对于每个输入行,awk 都会执行每个脚本代码块一次。然而,在许多编程情况中,可能需要在 awk 开始处理输入文件中的文本之前执行初始化代码。对于这种情况,awk 允许您定义一个 BEGIN 块。我们在前一个示例中使用了 BEGIN 块。因为 awk 在开始处理输入文件之前会执行 BEGIN 块,因此它是初始化 FS(字段分隔符)变量、打印页眉或初始化其它在程序中以后会引用的全局变量的极佳位置。

awk 还提供了另一个特殊块,叫作 END 块。awk 在处理了输入文件中的所有行之后执行这个块。通常,END 块用于执行最终计算或打印应该出现在输出流结尾的摘要信息。

awk 允许使用规则表达式,根据规则表达式是否匹配当前行来选择执行独立代码块。

awk 提供了完整的比较运算符集合,包括 "=="、"<"、">"、"<="、">=" 和 "!="。另外,awk 还提供了 "~" 和 "!~" 运算符,它们分别表示“匹配”和“不匹配”。它们的用法是在运算符左边指定变量,在右边指定规则表达式。以下示例脚本只输出包含字符序列 root 的那些行:

awk '/root/{ print $1}' /etc/passwd

awk 还提供了非常好的类似于 C 语言的 if 语句。如果您愿意,可以使用 if 语句重写前一个脚本:

{

                 if( $5 ~ /root/ ) {

                    print$3

                 }

}


awk 还允许使用布尔运算符 "||"(逻辑与)和 "&&"(逻辑或),以便创建更复杂的布尔表达式:

( $1 == "root" ) && ( $2 == "x" ) {print }/etc/passwd


awk 还允许我们执行整数和浮点运算。通过使用数学表达式,可以很方便地编写计算文件行数量的脚本。
awk '
BEGIN {
x=0
}
{
    x=x+1
}
END {
    print "There is " x " lines in the file"
}
' /etc/passwd
awk 有完整的数学运算符集合。除了标准的加、减、乘、除,awk还允许使用指数运算符 "^"、模(余数)运算符 "%" 和其它许多从 C 语言中借入的易于使用的赋值操作符。



NF 变量,也叫做“字段数量”变量。awk 会自动将该变量设置成当前记录中的字段数量。
awk '
BEGIN {
FS=":"
}
$1 == "root" {
print "There is " NF" segments in the line"
}
' /etc/passwd


记录号 (NR) 是另一个方便的变量。它始终包含当前记录的编号(awk 将第一个记录算作记录号 1)。迄今为止,我们已经处理了每一行包含一个记录的输入文件。对于这些情况,NR还会告诉您当前行号。

正确设置了 FS 变量之后,就可以将 awk 配置成分析几乎任何类型的结构化数据,只要这些数据是每行一个记录。然而,如果要分析占据多行的记录,仅仅依靠设置 FS 是不够的。在这些情况下,我们还需要修改 RS 记录分隔符变量。RS 变量告诉 awk 当前记录什么时候结束,新记录什么时候开始。
OFS 可以使打印的单字段之间打印 OFS 变量,我们可以方便地重新定义 OFS,这样 awk 将插入我们中意的字段分隔符。
awk '
BEGIN {
    FS=":"
    OFS=" "
}
$1 == "root" {
    print $1, $2, $3
}
' /etc/passwd


其中“,”不会被打印,逗号并不是实际文字字符串的一部分,只是告诉awk那是3个单独的字段。

  awk还有一个特殊变量 ORS,全称是“输出记录分隔符”。通过设置缺省为换行("\n") 的 OFS,我们可以控制在 print 语句结尾自动打印的字符,缺省 ORS 值会使 awk 在新行中输出每个新的 print 语句。如果想使输出的间隔翻倍,可以将 ORS 设置成 "\n\n"。或者,如果想要用单个空格分隔记录(而不换行),将 ORS 设置成 " "。

虽然大多数情况下 awk 的 print 语句可以完成任务,但有时我们还需要更多。在那些情况下,awk 提供了两个我们熟知的老朋友 printf() 和 sprintf()。是的,如同其它许多 awk 部件一样,这些函数等同于相应的 C 语言函数。printf() 会将格式化字符串打印到 stdout,而 sprintf() 则返回可以赋值给变量的格式化字符串。

你可能感兴趣的:(linux,shell,脚本,awk)