awk
awk基础
awk简介
awk是被设计用于文本处理,并常被用作数据提取和报告工具的解释性程序设计语言。awk的作者这样描述:awk是一个方便的且富有表现力的程序设计语言,它可以应用于各种各样的计算机和数据处理任务。
awk是数据驱动的,即:描述要处理的数据以及找到数据后要做什么。
和sed类似,awk的基本功能也是搜索文件中包含某些模式的行。当某行匹配到一个模式时,awk就再该行上执行指定的操作。awk持续地用这种方式处理输入的行,直到处理到输入文件的结尾为止。
awk一些基本功能:
-
使用变量操作由文本记录和字段组成的文本文件
-
具有算术和字符串操作符
-
具有普通的程序设计结构,如循环和条件
-
生成格式化报告
-
定义函数
-
从awk脚本中执行Linux命令
-
处理Linux命令的结果
-
更加巧妙地处理命令行的参数
-
更容易地处理多个输入流
awk基本语法
awk指令由一个模式(pattern)和跟一个动作(action)组成。动作被括在花括号内,用来与模式分割。每个awk指令之间通常用换行符来分割。
pattern {action} pattern {action} ...
运行awk的方式主要由两种:
-
如果awk程序很短,就直接运行写在awk的命令行中:
awk [options] [--] program-text file...
-
如果awk程序较长时,通常把它放在一个文件中更方便:
awk [options] -f program-file [--] file...
可以看到,一个awk命令由选项、awk程序文件或awk指令以及输入文件组成。输入是从指定的文件中读取。如果没有指定输入文件或指定为"-",那么awk从标准输入中(stdin)读取
常用的awk选项:
-
-F fs——指定用于输入数据的列分割符
-
-v var=value——在awk程序执行至前指定一个值value给变量var,只写变量值用于awk程序的BEGIN块
-
-f program-file——指定一个awk程序文件,代替在命令行指定的awk指令
-
"--"选项——根据POSIX参数解析约定,此选项表示命令行选项结束
第一个awk命令
测试文件:
[root@localhost awk]# pwd /mnt/test/shell/awk [root@localhost awk]# ls test.txt [root@localhost awk]# cat test.txt I like YOU but just LIKE you you should be brave and harry life was amazing 1234567890 run from cmd exopse copy add volume maintainer
把test.txt文件作为awk命令的输入文件,awk命令如下:
[root@localhost awk]# awk '{print}' test.txt I like YOU but just LIKE you you should be brave and harry life was amazing 1234567890 run from cmd exopse copy add volume maintainer
当调用awk时,text.txt为输入文件。awk会在此文件的每一行上按顺序地执行它的print命令,所有输出被送到标准输出
使用awk打印指定列
awk在处理已经被分割为多个逻辑列的文本方面非常优异。如:打印text.txt文件第一列:
[root@localhost awk]# awk '{print $1}' test.txt I you life 1234567890 run
awk默认使用空白符作为分割符,使用-F选项可以指定输入数据的列分割符。
[root@localhost awk]# awk -F : '{print $1}' /etc/passwd | head -n 3 root bin daemon
如果不加-F选项,打印出来是什么?
从awk程序文件读取awk指令
当awk指令过长时,就可以从awk程序文件中读取awk指令,具体语法:
awk -f mysqlscript.awk info.txt
如:
awk程序文件:
[root@localhost awk]# cat awk_gid.wak BEGIN { FS=":" } {print $3}
执行:
[root@localhost awk]# awk -f awk_gid.wak /etc/passwd | head -n 3 0 1 2
或者:
awk程序文件:
[root@localhost awk]# cat awk_gid2.wak {print $3}
执行:
[root@localhost awk]# awk -F : -f awk_gid2.wak /etc/passwd | head -n 3 0 1 2
awk的BEGIN和END块
正常情况下,awk对输入的每一行都会执行一次awk程序代码。但是,有时候需要在awk开始处理输入文本中的文本前执行一些初始化代码。对于这种情况,awk允许定义一个BEGIN模块。BEGIN块在awk开始处理输入文件至前被调用,所以它用于初始化FS变量(定义列分隔符)、打印标题、或者初始化其他在程序中的调用的全局变量。
如:
[root@localhost awk]# cat awk_gid3.awk BEGIN { print "start awk" FS=":" } {print $3} [root@localhost awk]# awk -f awk_gid3.awk /etc/passwd | head -n 4 start awk 0 1 2
同样,awk还提供END块。awk在输入文件中的所有行都被处理完之后,会执行END块中的内容。
awk中使用正则表达式
awk允许使用正则表达式来有选择的执行一个单独的代码块,取决于指定的正则表达式是否匹配到当前行。如:
[root@localhost awk]# awk '/YOU/{print}' test.txt I like YOU but just LIKE you
匹配到了含有YOU的行,然后输出
我们也可以使用操作符"~"(或者"!~")来指定任意列或变量匹配(或不匹配)一个正则表达式,这就是表达式。如:我们打印test.txt中第二列数据匹配到字符"a"的行的第一列:
[root@localhost awk]# awk '$2 ~ /a/ {print $0}' test.txt life was amazing
awk的表达式和块
awk还有很多其他方法可以由选择地执行代码块。可以将任意类型的布尔表达式放在代码块之前来控制特定的块什么时候可以执行,即当只由代码块前面的步而表达式为真时,才执行此代码块。如:输出文件/etc/passwd中第一列等于"root"的所有行的第三列
[root@localhost awk]# awk 'BEGIN{ FS=":"} $1 == "root" {print $3}' /etc/passwd 0
wak提供充分的比较操作符,如:"~"、"!~"、"=="、"<"、">"、">="、"<="和"!="等。一般情况,做标指定一个变量,右边指定一个正则表达式或者字符串。如:打印test.txt文件中匹配到字符串"you"的所有行
[root@localhost awk]# awk ' $0 ~ "you" {print}' test.txt I like YOU but just LIKE you you should be brave and harry
表达式时awk程序的基本组成部分,一个表达式可以对打印的、测试的,或传递给一个函数的内容进行求值。另外,一个表达式可以使用一个赋值操作符给一个变量或一列赋予一个新值。
awk的表达式包括变量、数组引用、常量和函数调用等。
awk的条件语句
awk也提供了类似于C语言的if语句。如:
[root@localhost awk]# awk '{if ($0 ~ "you") {print "if:" $0} else {print "others:" $1}} ' test.txt if:I like YOU but just LIKE you others: if:you should be brave and harry others:life others:1234567890 others:run
同样,awk允许使用步而操作符"||"和"&&"
[root@localhost awk]# awk '{if ($0 ~ "you" || $1 == "run") {print "if:" $0} else {print "others:" $1}} ' test.txt if:I like YOU but just LIKE you others: if:you should be brave and harry others:life others:1234567890 if:run from cmd exopse copy add volume maintainer
awk中的变量和操作符
awk允许执行整数和浮点数运算。
如:使用数学表达式,计算文件中空白行的awk程序。
[root@localhost awk]# cat awk_blank.awk BEGIN{ x=0 } /^$/ {x=x+1} END { print "there are " x " blank lines" } [root@localhost awk]# awk -f awk_blank.awk test.txt there are 1 blank lines
awk中的特殊变量
awk有自己特殊的变量。如:
-
FS:设置希望awk在列之间查找的字符序列。可以被设置为正则表达式
-
NF:列的数量。wak会自动将这个变量的值设置为当前记录中列的个数
[root@localhost awk]# awk 'NF == 3 {print}' test.txt life was amazing
输出有三列的行的数据
-
NR:记录当前记录的数量
如:打印输入文件text.txt第三行以后输入的记录
[root@localhost awk]# awk '{if(NR > 3) {print NR".\t" $0}}' test.txt 4. life was amazing 5. 1234567890 6. run from cmd exopse copy add volume maintainer
NR类似于指定从第几行开始才进行awk命令
awk中的循环结构
awk中也支持for、while和do-while循环结构。
[root@localhost awk]# cat awk_while.awk { i=1 while(i<=3){ {print $i} i++ } }
执行结果:
[root@localhost awk]# cat test.txt I like YOU but just LIKE you you should be brave and harry life was amazing 1234567890 run from cmd exopse copy add volume maintainer [root@localhost awk]# awk -f awk_while.awk test.txt I like YOU you should be life was amazing 1234567890 run from cmd
当awk处理第一行数据时,进行一次while循环,输出第一行数据的第一、二、三列。然后再去处理第二行数据,同样进入while循环,输出第二行数据的第一、二、三列。以此类推
for循环同样:
[root@localhost awk]# awk '{ for (i=1;i<3;i++) > print $i > }' test.txt I like you should life was 1234567890 run from
awk中的数据
awk也具有数组。在awk下,数组索引从1开始。定义数组方法:
arr[1]="fsx" arr[2]="123"
当awk遇到第一个赋值时,数组arr被创建并将arr[1]赋值为fsx。在第二个赋值语句执行后,数组arr就具有两个元素。
awk具有方便的机制来迭代数组中的元素:
for (x in arr){ print arr[x] }
print输出时不遵循指定规律,即arr[x]并不一定是有序的
awk同样支持使用字符串索引,如:
arr["name"]="fsx"
如果向删除awk数组中的某个元素,可以使用delete。
delete arr[1]
如果向查看数组中某个元素是否存在,可以使用特定的布尔操作符。
if (1 in arr) { print "arr[i] in" } else { print "arr[i] not in" }