AWK的简介和教程

AWK的简介和教程

AWK是一种强大的文本处理工具,它可以用简单的编程语言来实现复杂的文本操作。AWK是由Aho、Weinberger和Kernighan三位大牛在1977年开发的,因此也叫做AWK语言。AWK的名字来源于它们的姓氏首字母。

AWK的基本思想是将输入文件分割成多个记录和字段,然后对每个记录执行一系列的模式和动作。模式是一种条件表达式,用来匹配记录或字段。动作是一段AWK代码,用来处理匹配的记录或字段。

AWK有很多实现版本,其中最常用的是GNU AWK(gawk),它是GNU项目的一部分,拥有很多扩展功能。本文将以gawk为例来介绍AWK的基本用法和高级技巧。

AWK的基本语法

AWK的基本语法如下:

awk [options] 'program' file1 file2 ...

其中,options是一些可选的参数,如-F指定字段分隔符,-v指定变量赋值,-f指定程序文件等。program是一段AWK代码,通常由一对单引号包围。file1 file2 …是要处理的输入文件,可以有多个。

AWK程序由一系列的模式-动作对组成,每个模式-动作对之间用换行符或分号分隔。模式-动作对的格式如下:

pattern { action }

其中,pattern是一个条件表达式,可以是正则表达式、算术表达式、字符串表达式、逻辑表达式等。action是一段AWK代码,可以包含变量、运算符、函数、控制流等。如果省略pattern,则默认匹配所有记录。如果省略action,则默认打印匹配的记录。

例如,下面这个AWK程序打印所有包含foo的记录:

awk '/foo/' file

下面这个AWK程序打印所有第一个字段大于10的记录:

awk '$1 > 10' file

下面这个AWK程序打印所有记录的第二个字段,并在前面加上行号:

awk '{ print NR, $2 }' file

AWK的内置变量

AWK有很多内置变量,用来存储输入文件、记录和字段的相关信息。下面列举一些常用的内置变量:

  • FS:输入字段分隔符,默认为空格或制表符。
  • OFS:输出字段分隔符,默认为空格。
  • RS:输入记录分隔符,默认为换行符。
  • ORS:输出记录分隔符,默认为换行符。
  • NF:当前记录的字段数。
  • NR:当前记录的编号。
  • FNR:当前文件中的当前记录编号。
  • FILENAME:当前输入文件名。
  • ARGC:命令行参数个数。
  • ARGV:命令行参数数组。
  • ENVIRON:环境变量数组。

例如,下面这个AWK程序将输入文件中以逗号分隔的字段转换成以冒号分隔的字段:

awk 'BEGIN { FS = ","; OFS = ":" } { print $1, $2, $3 }' file

下面这个AWK程序将输入文件中每行末尾添加一个感叹号:

awk 'BEGIN { ORS = "!\n" } { print }' file

下面这个AWK程序打印每个文件中最后一行:

awk 'FNR == 1 && NR != 1 { print prev } { prev = $0 } END { print prev }' file1 file2 ...

AWK的数组

AWK支持一种特殊类型的数组,叫做关联数组(associative array)。关联数组可以使用任意类型的值作为索引(下标),而不仅仅是数字。关联数组在定义时不需要指定大小,在使用时可以动态增长。

例如,下面这个AWK程序统计输入文件中每个单词出现的次数,并按照字母顺序输出结果:

awk '{ for (i = 1; i <= NF; i++) count[$i]++ }
     END { for (word in count) print word, count[word] }' file | sort

注意,关联数组遍历时并不保证按照索引顺序输出,所以需要使用sort命令进行排序。

AWK的函数

AWK提供了很多内置函数,用来执行各种操作,如数学运算、字符串处理、时间格式化等。除了内置函数外,AWK还允许用户自定义函数。

数学函数

AWK提供了很多数学函数,如sin、cos、exp、log、sqrt等。这些函数接受一个数值参数,并返回一个数值结果。

例如,下面这个AWK程序计算输入文件中每个数字的平方根,并保留两位小数:

awk '{ printf "%.2f\n", sqrt($1) }' file

字符串函数

AWK提供了很多字符串函数,如length、index、substr、split等。这些函数接受一个或多个字符串参数,并返回一个字符串结果或一个数组。

例如,下面这个AWK程序计算输入文件中每行字符数,并输出最长行和最短行:

awk 'length > max { max = length; longest = $0 }
     length < min || min == 0 { min = length; shortest = $0 }
     END { print "Longest:", longest; print "Shortest:", shortest }' file

时间函数

GNU AWK提供了一些时间函数,如systime、strftime等。这些函数可以获取系统时间或格式化时间字符串。

例如,下面这个AWK程序在每行前面添加当前时间戳:

awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0 }' file

用户自定义函数

除了使用内置函数外,用户还可以自定义自己的函数。自定义函数需要在调用之前定义,并遵循以下语法:

function name(parameter-list) {
    statements
}

其中,name是函数名,parameter-list是参数列表(可以为空),statements是函数体。

例如,下面这个AWK程序定义了一个求两数最大值的函数,并在主程序中调用它:

function max(a, b) {
    if (a > b) return a
    else return b
}

{ print max($1, $2) }

AWK高级技巧

除了上述基本用法外,AWK还有很多高级技巧,可以让你更灵活地处理文本数据。下面介绍几个常见的高级技巧。

正则表达式

正则表达式是一种描述文本模式的语言,在AWK中可以广泛使用。正则表达式可以作为模式匹配记录或字段,也可以作为运算符匹配或替换字符串。

例如,下面这个AWK程序打印所有以大写字母开头并且包含数字的单词:

awk 'BEGIN { FS = "[ \t.,]+" }
     { for (i = 1; i <= NF; i++) if ($i ~ /^[A-Z].*[0-9]/) print $i }' file

上面的代码中,~是正则表达式匹配运算符,/是正则表达式的定界符,^是行首锚点,.是任意字符,*是重复零次或多次,[0-9]是数字字符类。

正则表达式还可以用于替换字符串,使用subgsub函数。sub函数只替换第一个匹配的子串,而gsub函数替换所有匹配的子串。它们的语法如下:

sub(regexp, replacement, target)
gsub(regexp, replacement, target)

其中,regexp是正则表达式,replacement是替换字符串,target是目标字符串。如果省略target,则默认为$0。

例如,下面这个AWK程序将输入文件中所有的foo替换成bar:

awk '{ gsub(/foo/, "bar"); print }' file

输入输出重定向

AWK可以使用输入输出重定向符来读写文件。输入重定向符是<,输出重定向符是>>>。其中,>表示覆盖写入文件,而>>表示追加写入文件。

例如,下面这个AWK程序将输入文件中每行的第一个字段写入到output.txt文件中:

awk '{ print $1 > "output.txt" }' file

注意,在AWK中使用输出重定向时,需要将文件名用双引号包围,并且不需要在print语句后面加分号。

输入重定向可以用于读取其他文件的内容,并与当前记录进行比较或处理。

例如,下面这个AWK程序将input.txt文件中每行的第一个字段与dict.txt文件中的每个单词进行比较,如果相同,则打印该行:

awk '{ while ((getline word < "dict.txt") > 0) 
        if ($1 == word) { print; break } 
      close("dict.txt") 
     }' input.txt

上面的代码中,getline函数用于从文件中读取一行,并返回读取状态。close函数用于关闭打开的文件。

BEGIN和END块

BEGIN和END块是两种特殊的模式-动作对,它们不依赖于输入文件的内容。BEGIN块在读取第一行之前执行,通常用于初始化变量、设置字段分隔符、打印标题等。END块在读取最后一行之后执行,通常用于打印汇总信息、清理资源等。

例如,下面这个AWK程序在BEGIN块中设置字段分隔符为逗号,在主程序中计算每行第二个字段的总和,在END块中打印总和:

awk 'BEGIN { FS = ","; sum = 0 }
     { sum += $2 }
     END { print "Sum:", sum }' file

多文件处理

AWK可以同时处理多个输入文件,并使用FILENAME变量来区分不同的文件名。当切换到新的输入文件时,FNR变量会重新从1开始计数,而NR变量会继续累加。

例如,下面这个AWK程序打印每个输入文件中最长的一行:

awk 'FNR == 1 { if (NR != 1) print max, file; max = 0; file = FILENAME }
     length > max { max = length; line = $0 }
     END { print max, file }' file1 file2 ...

上面的代码中,在处理每个新文件时,先判断是否需要打印上一个文件的结果,然后重置最大长度变量和当前文件名变量。在处理每一行时,如果长度大于最大长度,则更新最大长度变量和当前行变量。在处理完所有文件后,打印最后一个文件的结果。

le; max = 0; file = FILENAME }
length > max { max = length; line = $0 }
END { print max, file }’ file1 file2 …


上面的代码中,在处理每个新文件时,先判断是否需要打印上一个文件的结果,然后重置最大长度变量和当前文件名变量。在处理每一行时,如果长度大于最大长度,则更新最大长度变量和当前行变量。在处理完所有文件后,打印最后一个文件的结果。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

达分奇先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值