awk 用法

捍卫 awk

在这一系列的文章中,我将使您成为精通 awk 的编程人员。我承认,awk 并没有一个非常好听且又非常 “时髦” 的名字。awk 的 GNU 版本(叫作 gawk)听起来非常怪异。那些不熟悉这种语言的人可能听说过 "awk",而且可能认为它是一组落伍且过时的混乱代码。它甚至会使最博学的 UNIX 权威陷于混乱的边缘(使他不断地发出 "kill -9!" 命令,就象使用咖啡机一样)。

的确,awk 没有一个动听的名字。但它是一种很棒的语言。awk 适合于文本处理和报表生成,它还有许多精心设计的特性,允许进行多种方式的编程。与某些语言不同,awk 的语法较为常见。它借鉴了某些语言的一些精华部分,如 C 语言、python 和 bash(虽然在技术上,awk 比 python 和 bash 早创建)。awk 是一种一旦学会就会成为您战略代码库的重要部分的语言。


--------------------------------------------------------------------------------
回页首
第一个 Awk

您应该会看到 /ect/passwd 文件中的内容,本文使用该文件来解释 awk 的工作原理。当调用 awk 时,我们指定 /etc/passwd 作为输入文件。Awk 在执行期间对 /etc/passwd 文件中的每一行依次执行 print 命令。所有输出都发送到 stdout,可以得到类似 cat 命令的结果。

现在解释代码块 { print }。在 Awk 中,花括号用于将代码分块,这与 C 语言类似。我们的代码块中只有一条 print 命令。在 Awk 中,当 print 命令单独出现时,将打印当前行的全部内容。

$ awk '{ print $0 }' /etc/passwd
 


在 Awk 中,变量 $0 表示整个当前行,因此 print 和 print $0 的作用完全相同。

$ awk '{ print "" }' /etc/passwd
 

$ awk '{ print "hiya" }' /etc/passwd
 


运行该脚本,屏幕上讲显示多行 hiya。:)


--------------------------------------------------------------------------------
回页首
多个字段

print $1

$ awk -F":" '{ print $1 $3 }' /etc/passwd
 

halt7
operator11
root0
shutdown6
sync5
bin1
....etc.
 


print $1 $3

$ awk -F":" '{ print $1 " " $3 }' /etc/passwd
 


$1 $3

$ awk -F":" '{ print "username: " $1 "\t\tuid:" $3 }' /etc/passwd
 

username: halt          uid:7
username: operator      uid:11
username: root          uid:0
username: shutdown      uid:6
username: sync          uid:5
username: bin           uid:1
....etc.
 


--------------------------------------------------------------------------------
回页首
外部脚本

BEGIN {
 FS=":"
}
{ print $1 }
 


两种方法的区别在于如何设置字段分隔符。在该脚本中,(通过设置 FS 变量)在代码中指定字段分隔符,而前一示例通过在命令行向 awk 传递 -F":" 选项来设置 FS。一般而言,最好在脚本内部设置字段分隔符,因为这样可以少输入一个命令行参数。本文稍后将深入讲解 FS 变量。


--------------------------------------------------------------------------------
回页首
BEGIN 与 END 代码块

通常,awk 会针对每个输入行执行一次每个代码块。但是,在许多编程情形下,可能需要在 awk 开始处理输入文件的文本之前 执行初始化代码。对这种情况,awk 支持定义 BEGIN 代码块。前一示例使用了这种代码块。因为 BEGIN 代码块在 awk 开始处理输入文件之前执行,因此它是初始化 FS(字段分隔符)变量、打印页眉或者初始化在后续程序中将要引用的其他全局变量的绝佳位置。

另外,awk 还提供了另一种称为 END 的专用代码块。在输入文件的所有行处理完毕之后,awk 执行这个代码块。通常,END 代码块用于进行最终计算或者打印应该在输出流结尾处出现的汇总信息。


--------------------------------------------------------------------------------
回页首
正则表达式与代码块

/foo/ { print }
 

/[0-9]+\.[0-9]*/ { print }
 


--------------------------------------------------------------------------------
回页首
表达式与代码块

fred print

$1 == "fred" { print $3 }
 


root

$5 ~ /root/ { print $3 }
 


--------------------------------------------------------------------------------
回页首
条件语句

if

{
 if ( $5 ~ /root/ ) {
  print $3
 }
}
 


两个脚本的作用相同。第一个示例的布尔表达式位于代码块外,而第二个示例的代码块会针对每个输入行执行一次,本文使用 if 语句有选择地执行打印命令。两种方法都可以使用,可以选择与脚本的其他部分最匹配的方法。

if if

{
 if ( $1 == "foo" ) {
  if ( $2 == "foo" ) {
   print "uno"
  } else {
   print "one"
  }
 } else if ($1 == "bar" ) {
  print "two"
 } else {
  print "three"
 }
}
 


if

! /matchme/ { print $1 $3 $4 }
 

{  
 if ( $0 !~ /matchme/ ) {
  print $1 $3 $4
 }
}
 


两个脚本都会只输出不 包含 matchme 字符序列的行。也可以选择最适合您的代码的方法。它们的功能完全相同。

( $1 == "foo" ) && ( $2 == "bar" ) { print }
 


该示例只打印第一个字段等于 foo 且 第二字段等于 bar 的行。


--------------------------------------------------------------------------------
回页首
数值变量!

在 BEGIN 代码块中,我们将整型变量 x 初始化为零。这样,awk 每次遇到空白行时都将执行 x=x+1 语句,递增 x 值。在所有行都处理完毕之后,awk 执行 END 代码块,并打印最终的汇总信息,以显示它找到的空白行数。


--------------------------------------------------------------------------------
回页首
字符串化变量

2.01
 


1.01 x $( ) 1.01

{ print ($1^2)+1 }
 


稍做试验就可以发现,如果特定变量不包含效数字,那么 awk 在计算数学表达式时将该变量当作数值零处理。


--------------------------------------------------------------------------------
回页首
众多运算符

Awk 的另一个优点是它拥有全面的数学运算符。除了标准的加减乘除,awk 还支持前面演示的指数运算符 “^”、求模(余数)运算符 “%” 和借鉴自 C 语言的大量方便的赋值运算符。

其中包括前后加/减(i++、--foo),加减乘除赋值运算符(a+=3、b*=2、c/=2.2、d-=6.2)。而且,这仅仅是一部分 —— 我们还能使用方便的求模/指数赋值运算符(a^=2、b%=4)。


--------------------------------------------------------------------------------
回页首
字段分隔符

Awk 有其自己的特殊变量集合。其中一些变量支持调优 awk 性能,而且可以读取另一些变量来收集关于输入的重要信息。前面已经接触过特殊变量 FS。如前所述,这个变量支持设置 awk 期望在字段中找到的字符序列。当我们使用 /ect/passwd 作为输入时,FS 设为 ":"。尽管这样做可以解决问题,但 FS 还支持更高的灵活性。

FS="\t+"
 


上面使用特殊的正则表达式字符 “+”,表示 “一个或多个前一字符”。

FS="[[:space:]+]"
 


尽管该赋值运算符能够解决问题,但是并非必要。为什么呢?因为在默认情况下,FS 被设为单个空格字符,awk 将其解释为 “一个或多个空格或制表符”。在这个特定的示例中,默认的 FS 设置恰好是您最想要的设置。

FS="foo[0-9][0-9][0-9]"
 


--------------------------------------------------------------------------------
回页首
字段数目


 if ( NF > 2 ) {
  print $1 " " $2 ":" $3
 }
}
 


--------------------------------------------------------------------------------
回页首
记录数目

{
 #skip header
 if ( NR > 10 ) {
  print "ok, now for the real information!"
 }
}
 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值