三分薄地,认真耕耘

导航

 

1、概述

awk是专门为文本处理设计的编程语言,是一门数据驱动的编程语言,与sed类似都是以数据驱动的行处理软件,主要用于数据扫描、过滤、统计汇总工作,数据可以来自标准输入、管道或者文件。

awk在20世纪70年代诞生与贝尔实验室。现在使用的版本是1988年发布的Gnu awk

1.1 awk的几个变体

下面是几个AWK的变体:

  • AWK – 原先来源于 AT & T 实验室的的AWK
  • NAWK – AT & T 实验室的AWK的升级版
  • GAWK – 这就是GNU AWK。所有的GNU/Linux发布版都自带GAWK,它与AWK和NAWK完全兼容

1.2 awk典型用途

使用AWK可以做很多任务,下面是其中一些

  • 文本处理
  • 输出格式化的文本报表
  • 执行算数运算
  • 执行字符串操作等等

2、AWK工作流程基本语法

2.1 工作流程

AWK 执行的流程非常简单:读( Read )、执 行( Execute )与重复( Repeat )。下面的流程图描述出了 AWK 的工作流程:

1

2.2 语法结构


awk -[选项] 'BEGIN {awk-command-begin} {awk-command-body} END {awk-command-end}' 被执行文件

单引号包围的是整个 awk 程序。 单引号是必须存在的!!!! 双引号表示字符串,后面示例中有

2.2.1 awk常用选项

  • -v 变量赋值 该选项将一个值赋予一个变量,它会在程序开始之前进行赋值。

awk -v name=Jerry 'BEGIN{printf "Name = %s\n", name}
Name = Jerry

  • --dump-variables[=file] 该选项会输出排好序的全局变量列表和它们最终的值到文件中,默认的文件是 awkvars.out

$ awk --dump-variables '' 
$ cat awkvars.out 
ARGC: 1 
ARGIND: 0 
ARGV: array, 1 elements 
BINMODE: 0 
CONVFMT: "%.6g" 
ERRNO: "" 
FIELDWIDTHS: "" 
FILENAME: "" 
FNR: 0 
FPAT: "[^[:space:]]+" 
FS: " " 
IGNORECASE: 0 
LINT: 0 
NF: 0 
NR: 0 
OFMT: "%.6g" 
OFS: " " 
ORS: "\n" 
RLENGTH: 0 
RS: "\n" 
RSTART: 0 
RT: "" 
SUBSEP: "\034" 
TEXTDOMAIN: "messages"

  • --help 打印帮助信息

  • --lint[=fatal] 该选项允许检查程序的不兼容性或者模棱两可的代码,当提供参数 fatal的时候,它会对待Warning消息作为Error。


$ awk --lint '' /bin/ls 
awk: cmd. line:1: warning: empty program text on command line 
awk: cmd. line:1: warning: source file does not end in newline
awk: warning: no program text at all!

  • --posix:该选项开启严格的POSIX兼容
  • --profile[=file]: 该选项会输出一份格式化后的程序到文件中,默认文件是awkprof.out

$ awk --profile 'BEGIN{printf"---|Header|--\n"} {print} END{printf"---|Footer|---\n"}' marks.txt > /dev/null 
$ cat awkprof.out 
# gawk 配置, 创建 Wed Oct 26 15:05:49 2016 
# BEGIN 块 
BEGIN { 
    printf "---|Header|--\n"
} 
# 规则 
{ 
    print $0 
} 
# END 块 
END { 
    printf "---|Footer|---\n" 
}

  • --traditional 该选项会禁止所有的gawk规范的扩展。
  • -V 输出版本号
  • -F 指定字段分隔符。自定义输入数据的字段分隔符(默认为空格或制表符)awk -F':' '{print $1, $NF}' /etc/passwd -F 等价于内置变量 FS,也可在BEGIN块中设置(如 BEGIN{FS=":"})。
  • -f 从文件读取Awk命令,替代命令行直接输入。复杂脚本复用或长命令拆分,提升可维护性。awk -f demo.awk data.txt

2.2.2 BEGIN语句块

BEGIN语句块语法:

BEGIN {awk-commands}

BEGIN语句块在程序开始的使用执行,它只执行一次,在这里可以初始化变量。BEGIN是AWK的关键字,因此它必须为大写,注意,这个语句块是可选的。

2.2.3 BODY语句块

BODY语句块的语法:

/pattern/ {awk-commands}

BODY语句块中的命令会对输入的每一行执行,我们也可以通过提供模式来控制这种行为。注意,BODY语句块没有关键字。

2.2.4 END语句块

END语句块的语法

END {awk-commands}

END语句块在程序的最后执行,END是AWK的关键字,因此必须为大写,它也是可选的。

2.3 示例

2.3.1 示例文件

创建一个名为 marks.txt 的文件。其中包括序列号、学生名字、课程名称与所得分数


[root@entos7 awk_test]# cat marks.txt
1)    Amit     Physics    80
2)    Rahul    Maths      90
3)    Shyam    Biology    87
4)    Kedar    English    85
5)    Hari     History    89

我们将使用 AWK 脚本来显示输出文件中的内容,同时输出表头信息,最后一行输出文件行数

[root@entos7 awk_test]# awk 'BEGIN{printf "Sr No\tName\tSub\tMarks\n"} {print $0} END{print "Total Line="NR}' marks.txt
Sr No	Name	Sub	Marks
1)    Amit     Physics    80
2)    Rahul    Maths      90
3)    Shyam    Biology    87
4)    Kedar    English    85
5)    Hari     History    89
Total Line=5

程序启动时,AWK 在开始块中输出表头信息。在主体块中,AWK 每读入一行就将读入的内容输出至标准输出流中,一直到整个文件被全部读入为止。最后一行结束后,执行END语句块,打印文件行数。

3 AWK内置变量

AWK 提供了一些内置变量。 它们在你写 AWK 脚本的时候起着很重要的作用。 这一章节中将会展示如何使用这些内置变量。

内置变量列表如下:

变量名 说明
ARGC 表示在命令行提供的参数的个数。
ARGV 该变量为存储命令行输入参数的数组。数组的有效索引是从 0 到 ARGC-1
CONVFMT 此变量表示数据转换为字符串的格式,其默认值为 %.6g
ENVIRON 此变量是与环境变量相关的关联数组变量
FILENAME 此变量表示当前文件名称
NF 此变量表示当前输入记录的列数.
NR 此变量表示当前记录的行号。(译注:该变量类似一个计数器,统计记录的数量)
FNR 该变量与 NR 类似,不过它是相对于当前文件而言的。此变量在处理多个文件输入时有重要的作用。每当从新的文件中读入时 FNR 都会被重新设置为 0
FS 此变量表示输入的数据域之间的分隔符,其默认值是空格。 你可以使用 -F 命令行选项改变它的默认值
RS 此变量表示输入记录的分割符,其默认值为换行符
OFS 此变量表示输出域之间的分割符,其默认为空格
ORS 此变量表示输出记录(行)之间的分割符,其默认值是换行符
$0 当前处理行的整行内容
$n 当前处理行的第n个字段

3.1 ARGC

ARGC表示在命令行提供的参数个数


[root@entos7 awk_test]# awk 'BEGIN{print "Aaguments =", ARGC}' one two three four
Aaguments = 5

这里因为还有个默认参数awk,所有计算出来的参数为5个:awk one two three four

3.2 ARGV

这个变量是存储命令行输入参数的数组。数组的有效索引是从 0 到 ARGC-1。


[root@entos7 awk_test]# awk 'BEGIN{ for(i=0;i<ARGC;i++){print i,ARGV[i]} }' one two three four
0 awk
1 one
2 two
3 three
4 four

3.3 CONVFMT

此变量表示数据转换为字符串的格式,其默认值为 %.6g。


[root@entos7 awk_test]# awk 'BEGIN { print "Conversion Format =", CONVFMT }'
Conversion Format = %.6g

3.4 ENVIRON

此变量是与环境变量相关的关联数组变量。


[root@entos7 awk_test]# awk 'BEGIN {print ENVIRON["SHELL"],ENVIRON["USER"]}'
/bin/bash root

3.5 FILENAME

此变量表示当前文件名


# FILENAME在开始块中未定义,因此在BEGIN块中打印该参数为空
[root@entos7 awk_test]# awk 'BEGIN {print FILENAME}' marks.txt 

[root@entos7 awk_test]# awk 'END {print FILENAME}' marks.txt
marks.txt

值得注意的是在开始块中FILENAME是未定义的。

3.6 NF

此变量表示当前输入记录的列数。例如,下面这个例子只输出超过两个列的行:

[root@entos7 awk_test]# echo -e 'One\nOne Two\nOne Two Three\nOne Two Three Four'|awk 'NF > 2 {print}'
One Two Three
One Two Three Four

3.7 NR(number of row)

此变量表示当前记录的行号。(译注:该变量类似一个计数器,统计记录的数量)。下面例子会输出读入的前三行(NR<3)


[root@entos7 awk_test]# echo -e 'One\nOne Two\nOne Two Three\nOne Two Three Four'|awk 'NR < 3 {print}'
One
One Two

3.8 FNR

该变量与 NR 类似,不过它是相对于当前文件而言的。此变量在处理多个文件输入时有重要的作用。每当从新的文件中读入时 FNR 都会被重新设置为 0。

3.9 FS

此变量表示输入的数据域之间的分隔符,其默认值是空格。 你可以使用 -F 命令行选项改变它的默认值。

# 使用-F指定分隔符
[root@entos7 awk_test]# echo -e 'onegoodtwobadthreegoodfourbadfive'|awk -F 'good|bad' '{printf("%10s %10s\n",$1,$2)}'
       one        two

# 使用FS制定分隔符
[root@entos7 awk_test]# echo -e 'onegoodtwobadthreegoodfourbadfive'|awk -v FS='good|bad' '{printf("%10s %10s\n",$1,$2)}'
       one        two

3.10 RS(row separate)

此变量表示输入记录的分割符,其默认值为换行符。


[root@entos7 awk_test]# awk 'BEGIN {printf("RS=%10s",RS)}'
RS=

3.11 OFS

此变量表示输出的域(列)之间的分隔符,默认为空格


[root@entos7 awk_test]# awk 'BEGIN {printf("OFS=%-10s\n",OFS)}'
OFS=

3.12 ORS

此变量表示输出记录(行)之间的分割符,其默认值是换行符

3.13 $0

当前处理行的整行内容

3.14 $n

当前处理行的第n个字段(第n列)

awk '{print $1}' filename

4、运算符

与其它编程语言一样,AWK 也提供了大量的操作符。

4.1 算术运算符

`+加 -减 *乘 /除 %求余

详见以下示例


[root@entos7 awk_test]# awk 'BEGIN { a = 50;b = 20; printf("%d + %d = %d\n", a,b,a + b)}'
50 + 20 = 70 # + 求和
[root@entos7 awk_test]# awk 'BEGIN { a = 50;b = 20; printf("%d - %d = %d\n", a,b,a - b)}'
50 - 20 = 30 # - 求差
[root@entos7 awk_test]# awk 'BEGIN { a = 50;b = 20; printf("%d * %d = %d\n", a,b,a * b)}'
50 * 20 = 1000 # 求乘积
[root@entos7 awk_test]# awk 'BEGIN { a = 50;b = 20; printf("%d / %d = %d\n", a,b,a / b)}'
50 / 20 = 2 # 求除
[root@entos7 awk_test]# awk 'BEGIN { a = 50;b = 20; printf("%d %% %d = %d\n",a,b,a % b)}'
50 % 20 = 10 # 求余
[root@entos7 awk_test]# awk 'BEGIN {a = 2;b = 4; printf("a = %d, b = %d, a \^ b = %d\n", a, b, a ^ b)}'
a = 2, b = 4, a ^ b = 16 # 求乘方

[root@entos7 awk_test]# awk 'BEGIN {a = 2;b = 4; printf("a = %d, b = %d, a ** b = %d\n", a, b, a ^ b)}'
a = 2, b = 4, a ** b = 16 # 求乘方

4.2 增加运算符

自增自减与C语言一致++自增 --自减


[root@entos7 awk_test]# awk 'BEGIN {a = 10;b = ++a; printf("a = %d, b = %d\n", a, b)}'
a = 11, b = 11
[root@entos7 awk_test]# awk 'BEGIN {a = 10;b = --a; printf("a = %d, b = %d\n", a, b)}'
a = 9, b = 9
[root@entos7 awk_test]# awk 'BEGIN {a = 10; b = a++; printf("a = %d , b = %d\n", a, b)}'
a = 11 , b = 10
[root@entos7 awk_test]# awk 'BEGIN {a = 10; b = a--; printf("a = %d , b = %d\n", a, b)}'
a = 9 , b = 10

4.3 赋值运算符

赋值运算符包括: = 赋值运算符 += -= *= \= %= ^= **= 其中^=**=一样


[root@entos7 awk_test]# awk 'BEGIN { name = "Jerry";printf("name = %s\n", name) }'
name = Jerry
[root@entos7 awk_test]# awk 'BEGIN { a = 10; a += 10; printf("a = %d\n", a) }'
a = 20
[root@entos7 awk_test]# awk 'BEGIN { a = 10; a -= 10; printf("a = %d\n", b) }'
a = 0
[root@entos7 awk_test]# awk 'BEGIN { a = 10; a *= 2; printf("a = %d\n", a)}'
a = 20
[root@entos7 awk_test]# awk 'BEGIN { a = 10; a /= 2; printf("a = %d\n", a)}'
a = 5
[root@entos7 awk_test]# awk 'BEGIN { a = 2; a ^= 4; printf("a = %d\n", a)}'
a = 16
[root@entos7 awk_test]# awk 'BEGIN { a = 2; a **= 4; printf("a = %d\n", a)}'
a = 16

4.4 关系操作符

关系操作符如下:

  • == 等于,若两边相等,返回True,否则False
  • != 不等于,若两边不相等,返回True,否则False
  • <<= 小于,小于等于。若左侧小于(小于等于)右侧,返回Ture,否则False
  • > , >= 大于,大于等于。若左侧大于(大于等于)右侧,返回Ture,否则False

[root@entos7 awk_test]# awk 'BEGIN { a = 2; b = 4; if( a == b) printf("a == b\n");else printf("a != b\n") }'
a != b
[root@entos7 awk_test]# awk 'BEGIN { a = 2; b = 2; if( a == b) printf("a == b\n");else printf("a != b\n") }'
a == b
[root@entos7 awk_test]# awk 'BEGIN { a = 2; b = 4; if( a > b) printf("a > b\n"); else printf("a <= b\n")}'
a <= b
[root@entos7 awk_test]# awk 'BEGIN { a = 4; b = 2; if( a < b) printf("a < b\n"); else printf("a >= b\n")}'
a >= b

4.5 逻辑操作符

  • && 且,a && b。若a,b都为true,则true。a,b中有一个为false,则false。
  • || 或,a || b。a,b中一个为true,则true。a,b两个都为false,则false。
  • ! 非。!a。 a为True,则为false。a为false,则为true。

[root@entos7 awk_test]# awk 'BEGIN { num = 5; if( num >= 0 && num <=7) printf("%d is in octal format\n", num)}'
5 is in octal format
[root@entos7 awk_test]# awk 'BEGIN { ch = " "; if( ch == " " || ch == "\t") printf("ch is whitespace\n")}'
ch is whitespace
[root@entos7 awk_test]# awk 'BEGIN { name = "";if( !length(name) ) printf("name is empty string.\n")}'
name is empty string.

4.6 一元操作符

+ 取正值 -取负值


[root@entos7 awk_test]# awk 'BEGIN { a = -10; a = -a; printf("a = %d\n", a)}'
a = 10
[root@entos7 awk_test]# awk 'BEGIN { a = -10; a = +a; printf("a = %d\n", a)}'
a = -10

4.7 字符串连接符


awk 'BEGIN {str1="Hello,"; str2 = "World!"; str3 = str1 str2; printf("str3 is \"%s\"\n", str3)}'
str3 is "Hello,World!"

4.9 正则表达式操作符

正则表达式操作符使用 ~!~ 分别代表匹配和不匹配


[root@entos7 awk_test]# awk '$0 ~ 9' marks.txt
2)    Rahul    Maths      90
3)    Hari     History    89
[root@entos7 awk_test]# awk '$0 !~ 9' marks.txt
4)    Amit     Physics    80
5)    Shyam    Biology    87
6)    Kedar    English    85
# 匹配正则表达式需要在表达式前后添加反斜线,与js类似
$ tail -n 40 /var/log/nginx/access.log | awk '$0 ~ /ip\[127\.0\.0\.1\]/'

5、awk正则表达式

5.1 点(dot)

点字符(.)可以匹配除了行结束字符的所有字符,只能出现一次,且必须出现一次。比如下面的便子就可以匹配 fin, fun, fan 等等。

echo -e "cat\nbat\nfun\nfin\nfn\nfaan" | awk '/f.n/'
fun 
fin

5.2 行开始

行开始符(^)匹配一行的开始。下面的示例将输出所有以字符串 The 开始的行


echo -e "This\nThat\nThere\nTheir\nthese" | awk '/^The/'
There 
Their

5.3 行结束

行结束符($)匹配一行的结束。下面的例子中将输出所有以字符 n 结束的行


echo -e "knife\nknow\nfun\nfin\nfan\nnine" | awk '/n$/'
fun 
fin 
fan

5.4 匹配字符集

匹配字符集用于匹配集合(由方括号表示)中的一个字符。如下例子中,匹配 Call 与 Tall 而不会匹配 Ball

echo -e "Call\nTall\nBall" | awk '/[CT]all/'

Call 
Tall

5.5 排除集

正则匹配时会排除集合中的字符。如下例子中只会输出 Ball。


echo -e "Call\nTall\nBall" | awk '/[^CT]all/'

Ball

5.6 或选择

竖线(|)允许正则表达式实现逻辑或运算. 下面例子将会输出 Ball 与 Call


echo -e "Call\nTall\nBall\nSmall\nShall" | awk '/Call|Ball/'

Call 
Ball

5.7 最多出现一次

该符号( ?)前面单个字符出现0次或者出现一次。如下示例匹配 Colour 与 Color。 使用 ? 使得 u 变成了可选字符 。


echo -e "Colour\nColor" | awk '/Colou?r/'

Colour 
Color

5.8 出现零次或多次

该符号(*) 允许其前面单个字符出现多次或者0次。如下示例将匹配 ca,cat, catt 等等。


echo -e "ca\ncat\ncatt" | awk '/cat*/'
ca 
cat 
catt

5.9 出现一次或多次

该符号(+)使得其前的字符出现一次或者多次。下面的例子会匹配一个 2 或者多个连续的 2


echo -e "111\n22\n123\n234\n456\n222" | awk '/2+/'
22 
123 
234 
222

5.10 分组

括号用于分组而字符 | 用于提供多种选择。如下的正则表达式会匹配所有包含 Apple Juice 或 Aplle Cake 的行。

与前面 [] 区别在于,[]是取单个字符,而这里是取一个字符串


echo -e "Apple Juice\nApple Pie\nApple Tart\nApple Cake" | awk '/Apple (Juice|Cake)/'

Apple Juice  
Apple Cake

6、控制语句

6.1 IF语句

条件语句测试条件,然后根据条件执行相应的动作。条件语句语法:

if (condition)
    action

也可以使用花括号{}来执行一组操作


if (condition)
{
    action-1
    action-2
    action-3
    .
    .
    .
    action-n

}

下面的例子判断数字是奇数还是偶数:


[root@entos7 awk_test]# seq 10 | awk '{if($1 % 2 == 0) printf("%d is even number.\n",$1)}'
2 is even number.
4 is even number.
6 is even number.
8 is even number.
10 is even number.

6.2 IF_ELSE语句

if-else语句中允许在条件为假时执行另外一组的动作。下面为 if-else 的语法格式:


if (condition) 
    action-1 
else 
    action-2

其中,条件为真时执行 action-1,条件为假时执行 action-2。下面是使用该语句判断数字是否为偶数的例子:


[root@entos7 awk_test]# seq 10 | awk '{if($1 % 2 == 0) printf("%d is even number.\n",$1); else printf("%d is odd num.\n", $1)}'
1 is odd num.
2 is even number.
3 is odd num.
4 is even number.
5 is odd num.
6 is even number.
7 is odd num.
8 is even number.
9 is odd num.
10 is even number.

6.3 if-elseif梯

我们可以很轻松地使用多个 if-else 语句构造 if-else-if 梯从而实现多个条件的判断。示例如下:


awk 'BEGIN { a=30; \
if (a==10) print "a = 10";\
else if (a == 20) print "a = 20"; \
else if (a == 30) print "a = 30"; \
}'


a = 30

7、循环

7.1 For循环

语法如下:


for (initialisation; condition; increment/decrement) 
    action

for 语句首先执行初始化动作( initialisation ),然后再检查条件( condition )。如果条件为真,则执行动作( action ),然后执行递增( increment )或者递减( decrement )操作。只要条件为真循环就会一直执行。每次循环结束都会进条件检查,若条件为假则结束 循环。下面的例子使用 For 循环输出数字 1 至 5:


[root@entos7 awk_test]# awk 'BEGIN{ for(n=1; n<6; n++) printf("%d\n", n) }'
1
2
3
4
5

7.2 while循环

While 循环会一直执行动作直到逻辑条件为假为止。其使用方法如下:


while (condition) 
    action

AWK 首先检查条件是否为真,若条件为真则执行动作。此过程一直重复直到条件为假时,则停止。下面是使用 While 循环输出数字 1 到 5 的例子


[root@entos7 awk_test]# awk 'BEGIN{ n=1; while(n<6){ printf("%d\n",n);n++ } }'
1
2
3
4
5

6.3 Do-while

Do-While 循环与 While 循环相似,但是 Do-While 的条件测试放到了循环的尾部。下面是 do-while 的语法


do 
    action 
while (condition)

在 do-while 循环中,无论条件是真是假,循环语句至少执行一次,执行后检查条件真假。下面是使用 do-While 循环输出数字 1 到 5 的例子:


[root@entos7 awk_test]# awk 'BEGIN { n=1; do {printf("%d\n",n); ++n} while(n<6) }'
1
2
3
4
5

6.4 break

顾名思义,break 用以结束循环过程(break只跳出当前的循环,如果想要进行多层循环操作,则需要在后面加数字,如 break 2)。在下面的示例子中,当计算的和大于 50 的时候使用 break 结束循环过程:


[root@entos7 awk_test]# awk 'BEGIN { sum = 0;for(i=0; i<=20; i++){ sum = sum + i; if(sum < 50) printf("sum is %d\n",sum); else break;} }'
sum is 0
sum is 1
sum is 3
sum is 6
sum is 10
sum is 15
sum is 21
sum is 28
sum is 36
sum is 45

7.5 continue

Continue 语句用于在循环体内部结束本次循环,从而直接进入下一次循环迭代。(coninue只结束当前的循环,如果想要结束多层循环操作,则需要在后面加数字,如 continue 2)当我们希望跳过循环中某处数据处理时就会用到 Continue。下面的例子输出 1 到 20 之间的偶数:


[root@entos7 awk_test]# awk 'BEGIN{ for(i=0; i<20; i++){ if(i % 2 == 0) printf("%d\n", i); else continue} }'
0
2
4
6
8
10
12
14
16
18


7.6 exit

Exit 用于结束脚本程序的执行。该函数接受一个整数作为参数表示 AWK 进程结束状态。 如果没有提供该参数,其默认状态为 0 。下面例子中当和大于 50 时结束 AWK 程序。


[jerry]$ awk 'BEGIN {
    sum = 0; for (i = 0; i < 20; ++i) {
        sum += i; if (sum > 50) exit(10); else print "Sum =", sum 
                                     } 
                    }'


Sum = 0 
Sum = 1 
Sum = 3 
Sum = 6 
Sum = 10 
Sum = 15 
Sum = 21 
Sum = 28 
Sum = 36 
Sum = 45

让我们检查一下脚本执行后的返回状态:


echo $?
10

8 awk数组相关

8.1 基本概念

awk中数组的下标可以是数字和字母(类似pyhton中的字典),数组的下标通常被称为关键字(key)。值和关键字都存储在内部的一张针对key/value应用hash的表格里。由于hash不是顺序存储,因此在显示数组内容时会发现,它们并不是按照你预料的顺序显示出来的。数组和变量一样,都是在使用时自动创建的,awk也同样会自动判断其存储的是数字还是字符串。一般而言,awk中的数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等。

8.2 数组创建及赋值

创建数组的方式非常简单,直接为变量赋值即可


[root@entos7 awk_test]# awk 'BEGIN { \
arr[0] = 1; arr[1] = 2; arr[2] = 3;
for (i = 0; i < 3; i++) { printf("a[%d] is %d\n", i, arr[i]) }
}'

a[0] is 1
a[1] is 2
a[2] is 3

[root@entos7 awk_test]# vim dict_test.awk
#!/usr/bin/awk -f

BEGIN {
	fruits["mango"] = "orange";
	fruits["orange"] = "orange";
	printf("mango's color is %s\n", fruits["mango"]);
	printf("orange's color is %s\n", fruits["orange"]);
}

[sc_test@vlogin02 ~]$ ./dict_test.awk
mango's color is orange
orange's color is orange

8.3 删除数组元素

使用delete删除数组元素

[root@entos7 awk_test]# vim dict_delete.awk
#!/usr/bin/awk -f

BEGIN{
    fruits["mango"] = "yellow";
    fruits["apple"] = "red";
    fruits["orange"] = "orange"; # 删除orange数组
    delete fruits["orange"];
    for(i in fruits) {
        printf( "%s's color is %s\n", i, fruits[i]);
    }
}
[root@entos7 awk_test]# ./dict_delete.awk
mango's color is yellow
apple's color is red
# 数组元素 fruits["orange"]已被删除

8.4 遍历数组

使用方法:


for(变量 in 数组名){ 
    动作指令序列 
}

示例

[root@entos7 awk_test]# vim dict_allaccess.awk
#!/usr/bin/awk -f

BEGIN{
    fruits["mango"] = "yellow";
    fruits["apple"] = "red";
    fruits["orange"] = "orange";
    for(i in fruits) {
        printf( "%s's color is %s\n", i, fruits[i]);
    }
}
[root@entos7 awk_test]# ./dict_allaccess.awk
orange's color is orange
mango's color is yellow
apple's color is red

8.5 多维数组

awk不支持多维数组,但是可以通过指定key值进行模仿

例如一个3*3的数组


100 200 300 
400 500 600 
700 800 900

可以通过以下方式进行模仿



[root@entos7 awk_test]# vim Multidimen.awk
#!/usr/bin/awk -f

BEGIN {
   array["0,0"] = 100;
   array["0,1"] = 200;
   array["0,2"] = 300;
   array["1,0"] = 400;
   array["1,1"] = 500;
   array["1,2"] = 600;

   # print array elements
   print "array[0,0] = " array["0,0"];
   print "array[0,1] = " array["0,1"];
   print "array[0,2] = " array["0,2"];
   print "array[1,0] = " array["1,0"];
   print "array[1,1] = " array["1,1"];
   print "array[1,2] = " array["1,2"];
}
[root@entos7 awk_test]# chmod +x Multidimen.awk
[root@entos7 awk_test]# ./Multidimen.awk
array[0,0] = 100
array[0,1] = 200
array[0,2] = 300
array[1,0] = 400
array[1,1] = 500
array[1,2] = 600

9、awk脚本文件

9.1 基本信息

类别 内容
shebang 使用#!/usr/bin/awk -f声明。awk路径可以通过which awk确认
脚本结构 包含BEGIN,BODY主处理逻辑,END三个部分
执行方式 可以直接运行(需要可执行权限)或通过awk -f script.awk执行
文件权限 需要赋予脚本可执行权限:chmod +x script.awk
输入涟源 支持标准输入、管道输入和文件输入
跨平台兼容性 在Ubuntu、Cetnos、EulerOS上行为一致

9.2 示例

示例一:打印信息


[root@entos7 awk_test]# vim hello.awk
#!/usr/bin/awk -f

BEGIN {
    print "Hello World from awk!";
}

[root@entos7 awk_test]# chmod +x hello.awk
[root@entos7 awk_test]# ./hello.awk
Hello World from awk!

示例二:打印/etc/passwd文件中41行至55开始的用户名,用户ID,组ID,用户家目录,bash


[root@entos7 awk_test]# vim user_info.awk
#!/usr/bin/awk -f


BEGIN {
    FS = ":";
    printf("用户名\t用户ID\t用户组ID\t用户家目录\t用户shell\n")
}


# BODY主逻辑部分
{
    if( NR > 40 && NR < 56 ) printf("%s\t%s\t%s\t%s\t%s\n", $1, $3, $4, $6, $7)
}


END {
    printf("用户作数为:%10d\n", NR)
}

[root@entos7 awk_test]# chmod +x user_info.awk
[root@entos7 awk_test]# ./user_info.awk /etc/passwd
用户名	用户ID	用户组ID	用户家目录	用户shell
sssd	989	983	/	/sbin/nologin
dirsrv	988	982	/usr/share/dirsrv	/sbin/nologin
setroubleshoot	987	981	/var/lib/setroubleshoot	/sbin/nologin
saned	986	980	/usr/share/sane	/sbin/nologin
hsqldb	96	96	/var/lib/hsqldb	/sbin/nologin
tomcat	53	53	/usr/share/tomcat	/sbin/nologin
pkiuser	17	17	/usr/share/pki	/sbin/nologin
gdm	42	42	/var/lib/gdm	/sbin/nologin
gnome-initial-setup	985	979	/run/gnome-initial-setup/	/sbin/nologin
pcp	984	978	/var/lib/pcp	/sbin/nologin
kdcproxy	983	977	/	/sbin/nologin
ipaapi	982	976	/	/sbin/nologin
sshd	74	74	/var/empty/sshd	/sbin/nologin
avahi	70	70	/var/run/avahi-daemon	/sbin/nologin
postfix	89	89	/var/spool/postfix	/sbin/nologin
用户作数为:        58

本文主要参考了一下博客,再次特别感谢

三十分钟学会AWK
深入解析awk编程:工作流程、内置变量与控制结构
awk命令详解

posted on 2025-07-16 10:42  平复心态  阅读(128)  评论(0)    收藏  举报