
在awk中,我们提到awk由模式动作组成. 关于模式,我们已经讨论过awk--pattern(模式),让我们看一下awk的动作.
我们还引用了awk模式中使用的示例:
//打印当前目录下面,大小大于1K(1024)的文件或目录名称
ls -l | awk 'NR > 1 && $5 > 1024 {print $9}'
粗体部分是动作. 此处的操作是打印第9个字段,除以awk,
因此可以认为awk中的执行主要是通过模式匹配来匹配的,然后在匹配正确之后执行操作.
awk动作主要包括两种类型:
1. 正则表达式(包括设置常量,变量,赋值,函数调用(包括print,printf和自定义函数))
2. 流程(例如,如果while for等)
Awk只有两种数据类型:
1)字符串
2)值
互相转换
字符串是指用双引号(“”)括起来的字符串. 字符串和数值可以根据情况进行转换.
当您需要强制转换时,可以使用:
1)字符串->值: 字符串+ 0(因为0对数组没有影响-),例如“ 1” + 0
2)数值->字符串: 数字“”,例如1“”;
支持操作
1)字符串只有一个运算符: 串联
比如:
awk -F "\|\|" '{print $1":"$2}' worker.txt
输出:
1:Jack
2:Lip
2)对于数值: awk支持的常规C运算符操作,例如: ++,-..等.
(1)ARGC / ARGV
含义: 输入行参数的数量/数组
示例: 省略
(2)文件名
含义: 当前输入行的文件名
示例: 当有多个文件时,您可以区分不同的输入行,
awk '{ if(FILENAME=="worker.txt") { print 1 } else{ print 2} }' worker.txt countries
(3)NR
含义: 当前输入行的序列号(连续累加)
示例:
awk '{printf("%s ",NR)} END{printf("\n")}' worker.txt countries
输出:1 2 3 4 5 6 7 8 9 10 11 12 13
(4)FNR
含义: 当前输入行与输入内容的序列号(每个输入将独立排名)
示例:
awk '{printf("%s ",FNR)} END{printf("\n")}' worker.txt countries
输出:1 2 1 2 3 4 5 6 7 8 9 10 11
注意: 当有多个文件时,NR会不断累积,因此当只有两个输入时,您只需要根据NR和FNR来区分输入源,
例如(2)可以将FILENAME的示例修改为:
awk 'NR==FNR{ print 1} NR > FNR{ print 2 }' worker.txt country
(5)NF
含义: 当前输入行的字段总数(可以理解为: ALineInput.splite(`FS`).count())

示例:
awk -F "\|\|" '{printf("当前输入行的字段数:%d,输入行:%s\n",NF,$0)}' worker.txt
输出:
当前输入行的字段数:5,输入行:1||Jack||25||man||Chinese,FuJian
(6)FS / OFS
含义: 设置输入/输出分隔符
示例:
awk 'BEGIN{FS="\|\|";printf("%3s\n","ID")} {printf("%.3d\n",$1)}' worker.txt
或
awk –F "\|\|" '{printf("%3s\n","ID")} {printf("%.3d\n",$1)}' worker.txt
(7)RS / ORS
含义: 输入/输出记录分隔符
示例: 省略,默认为RS = ORS =“ \ n”
(8)OFMT
含义: 数字输出格式
示例: 省略
(9)长度/ RSTART
含义: awk的内置函数match(s,r)(匹配函数)的返回值,其中RLENGTH(右长度)表示匹配长度,RSTART表示输入线s匹配r的起始位置
示例:
//匹配输入行是否存在字符串"Chinese"
awk -F "\|\|" '{match($0,"Chinese");if(RLENGTH > 1) printf("\"Chinese\" can match in \"%s\",RSTART:%d,RLENGTH:%d\n",$0,RSTART,RLENGTH)}' worker.txt
输出:
"Chinese" can match in "1||Jack||25||man||Chinese,FuJian",RSTART:19,RLENGTH:7
可见RSTART的计数是由1开始的
(10)昏迷
含义: 下标分隔符
示例: 省略,默认为SUBSET =“ \ 34”
用户定义变量的首字母不能为数字. 您需要在命令行前面设置变量. 您可以使用awk --v键=值方法,
例如:
//设置在动作中使用的自定义变量current_path
awk -v current_path = `pwd` '{print current_path}' input
您还可以使用以下方法:
var="var!"
awk 'BEGIN{print "'$var'"}' empty.txt
输出为:
var!
似乎变量var的值不能包含空格(环境: Ubuntu14.04,bash).
awk提供了用于存储字符串和值的一维数组. 数组和数组元素不需要事先声明,也不需要指定数组中有多少个元素.
像变量一样,将在提及时创建数组元素,数组元素的默认初始值为0或空字符串“”.
awk的下标使用字符串,因此它们也称为关联数组(类似于哈希或映射).
例如:
awk '/Asia/ {pop["Asia"] += $3} END {print "Asia populate:", pop["Asia"]}' countries
输出:
Asia populate: 2173
有两种方法可以在awk中遍历数组
方法1)for(i = 0; i <**; i ++){}
方法2)(用于数组中的值){}(即foreach)
方法1的缺点是我们需要知道当前数组的数量,因此它更适合awk中的方法2.
注意: 如果需要确定元素是否存在于数组中,则可以使用以下方法:
if(数组中的val)
例如:
如果(流行的是“亚洲”)
如果if(数组[variable]!= **)且**为空,则if返回true,
原因是在数组[variable]期间,如果awk判断带有下标变量的元素不存在,则默认情况下它将创建一个空字符串.

1)只需删除一个删除数组[val]
2)删除所有(数组中的val)删除数组[val]
实际上,awk不提供多维数组,但是由于awk的下标使用了字符串,因此您可以按照自己的方式构造多维数组awk数组长度,例如:
awk '{for(i = 1; i <=3; i++) {for(j=1;j<=3;j++) {pop[i""j]=i*j}}} END{for (data in pop) {print "sub=",data,"data:",pop[data]}}' worker.txt
输出为:
sub= 11 data: 1
sub= 12 data: 2
sub= 13 data: 3
sub= 21 data: 2
sub= 22 data: 4
sub= 23 data: 6
sub= 31 data: 3
sub= 32 data: 6
sub= 33 data: 9
弹出[i“” j]的地方是将数值转换为字符串
1)内置数字功能
Awk内置的算术函数类似于C语言,包括:
罪(x)
cos(x)
atan2(y,x)
rand()
品牌(x)
exp(x)
日志(x)
sqrt(x)
int(x)
例如:
awk 'BEGIN{print "sqrt(4) =",sqrt(4)}' empty.txt
输出:
sqrt(4) = 2
2)内置字符功能
awk中字符串的内置函数与C的存在稍有不同,主要包括以下内容:
(1)sub(r,s)含义: 将$ 0的最左边和最长的r替换为s,并返回替换次数
sub(r,s,t)含义: 用s替换t中最左边和最长的r,然后返回替换次数
例如:
awk -F "\|\|" '{sub("man","female",$0);print}' worker.txt
输出为:
1||Jack||25||female||Chinese,FuJian
2||Lip||30||female||American
(2)gsub(r,s)含义: 将输入行中的字符串r替换为s,并返回替换出现的次数
gsub(r,s,t)的含义: t是输入行,用s代替出现在t中的字符串r
例如:
awk '{gsub("man","female"); print $0}' worker.txt
输出为:
1||Jack||25||female||Chinese,FuJian
2||Lip||30||female||American
awk '{gsub("man","female",$0); print $0}' worker.txt
输出为:
1||Jack||25||female||Chinese,FuJian
2||Lip||30||female||American
也:
对于在sub或gsub上执行的替换,任何字符&in s的出现都将替换为r. (即&= r)
例如:
awk '{gsub(/a/,"\"&*&\"",$0); print}' worker.txt
输出为:
1||J"a*a"ck||25||m"a*a"n||Chinese,FuJi"a*a"n
2||Lip||30||m"a*a"n||Americ"a*a"n
即:使用“a*a”替换原本的a
(3)索引(s,t)
含义: 返回字符串t在s中第一次出现的位置awk数组长度,如果找不到则返回0
例如:
awk '{print "\"man\" index:" index($0,"man")}' worker.txt
输出为:
"man" index:14
"man" index:13
(4)个长度
含义: 返回字符串s的长度
例如:
awk -F "\|\|" '{printf("\"%s\" length:%d\n",$2,length($2))}' worker.txt
输出为:
"Jack" length:4
"Lip" length:3

(5)个匹配项(s,r)
含义: 测试s是否包含可以与r匹配的字符串,返回s中匹配的起始位置,并设置内置变量RSTART,RLENGTH
例如:
awk -F "\|\|" '{match($0,"Chinese");if(RLENGTH > 1) printf("\"Chinese\" can match in \"%s\",RSTART:%d,RLENGTH:%d\n",$0,RSTART,RLENGTH)}' worker.txt
输出为:
"Chinese" can match in "1||Jack||25||man||Chinese,FuJian",RSTART:19,RLENGTH:7
可见RSTART的计数是由1开始的
(6)split(s,a)含义: 使用FS将s拆分为数组a并返回字段数
split(s,a,fs)的含义: 使用fs将s拆分为数组a并返回字段数
例如:
awk 'BEGIN { FS="\|\|"} {iAddress = split($5,Address,","); for(i=1;i<=iAddress;i++){ printf("currunt %d Address:%s\n",i,Address[i])} }' worker.txt
输出为:
currunt 1 Address:Chinese
currunt 2 Address:FuJian
currunt 1 Address:American
可见在split中数组存储的顺序为arr[“1”],arr[“2”]....
(7)sprintf(fmt,expr列表)
含义: 根据格式设置字符串格式,并返回生成的格式字符串
例如:
awk -F "\|\|" '{print sprintf("id:%d name:%s",$1,$2)}' worker.txt
输出为:
id:1 name:Jack
id:2 name:Lip
如果在awk中使用自定义函数,则可以使用function关键字
例如:
awk 'BEGIN{print max(1,2) } function max(m,n) { return m > n ? m : n}' empty.txt
输出:2
awk 'BEGIN{ myprint("hello,world") } function max(m,n) { return m > n ? m : n} function myprint(x){print x}' empty.txt
输出: hello,world
awk中流控制语句的用法类似于C语言
1)if..else ..
例如:
//区分多个输入的方法(缺点需要知道输入的文件名称)
awk -F "\|\|| " '{if(FILENAME == "worker.txt") {print "input is worker.txt",$2} else if(FILENAME == "countries") { print "input is countries",$4}}' worker.txt countries
2)/暂停/暂停
省略
1)输出到标准输出(默认)
例如:
awk -F "\|\|" '{print sprintf("id:%d name:%s",$1,$2)}' worker.txt
输出:
id:1 name:Jack
id:2 name:Lip
2)输出到文件
比如:
awk -F "\|\|" '{print sprintf("id:%d name:%s",$1,$2) > "test.txt"}' worker.txt
cat test.txt内容为: id:1 name:Jack id:2 name:Lip
注意:
如果在同一程序中有文件输出(例如上述内容: test.txt),则在以后的过程中需要读取该文件(例如: test.txt),则必须阅读“关闭之前”文件(将缓存的内容写入文件),然后读取文件.
关闭方式是:
关闭(“ test.txt”);
3)输出到管道
例如:
awk -F "\|\|" '{print "/" |"df" }' worker.txt
输出:
文件系统 1K-块 已用 可用 已用% 挂载点
udev 1946180 4 1946176 1% /dev
tmpfs 391988 1136 390852 1% /run
/dev/dm-0 611014912 16737160 563216968 3% /
none 4 0 4 0% /sys/fs/cgroup
none 5120 0 5120 0% /run/lock
none 1959932 152 1959780 1% /run/shm
none 102400 72 102328 1% /run/user
/dev/sda1 240972 110988 117543 49% /boot
1)来自文件
比如:
awk '{print }' worker.txt
输出:
1||Jack||25||man||Chinese,FuJian
2||Lip||30||man||American
2)来自标准输入
例如:
awk '{print }' //回显
输入/输出:
Hello,World
Hello,World
3)从管道

例如:
cat worker.txt | awk '{print}'
输出:
1||Jack||25||man||Chinese,FuJian
2||Lip||30||man||American
4)从getline
顾名思义,getline有6种调用方式:
表达
变量集
getline
$ 0,NF,NR,FNR
getline var
var,NR,FNR
getline <文件
$ 0,NF
getline var <文件
cmd | getline
$ 0,NF
cmd | getline var
注意:
使用getline的返回值有3种情况: 1(记录存在),0(文件末尾),-1(打开失败或不存在)
对于awk中的判断语句(如果,同时,针对),0 =假,不是0 =真
因此,如果您采用;
awk'END {while(getline <“ no_exist_file”){print $ 0}}'empty.txt
它将进入一个无限循环,所以正确的书写方式是:
awk'END {while(getline <“ no_exist_file”> 0){print $ 0}}'empty.txt
让我们看一下getline的具体用法:
1)getline
awk '{while(getline > 0) {print $0}}' worker.txt
输出为:
2||Lip||30||man||American
2)getline var
awk '{while(getline var > 0) {print var}}' worker.txt
输出为:
2||Lip||30||man||American
为什么1,2仅有一行输出呢?
getline函数的功能在于抓取下一个记录.
3)getline <文件
awk 'END{while(getline < "worker.txt" > 0) print $0,"NF=",NF}' empty.txt
输出为:
1||Jack||25||man||Chinese,FuJian NF= 1
2||Lip||30||man||American NF= 1
4)getline var <文件
awk 'END{while(getline var< "worker.txt" > 0) print var}' empty.txt
输出为:
awk 'END{while(getline var< "worker.txt" > 0) print var}' empty.txt
5)cmd | getline
awk '{while("who" | getline > 0) print "NF(Current Line Splite Count):",NF,"data:",$0}' worker.txt
输出为:
NF(Current Line Splite Count): 5 data: lin :0 2016-11-19 16:55 (:0)
NF(Current Line Splite Count): 5 data: lin pts/2 2016-11-19 19:57 (:0)
NF(Current Line Splite Count): 5 data: lin pts/13 2016-11-19 20:49 (:0)
NF(Current Line Splite Count): 5 data: lin pts/25 2016-11-19 21:16 (:0)
6)cmd |获取行var
awk '{while("who" | getline line > 0) print line}' worker.txt
输出为:
lin :0 2016-11-19 16:55 (:0)
lin pts/2 2016-11-19 19:57 (:0)
lin pts/13 2016-11-19 20:49 (:0)
lin pts/25 2016-11-19 21:16 (:0)
可以看到:
直接使用awk的输入(文件/管道/标准输入)时,将使用getline,并根据实际情况设置$ 0(变量),NR,FNR.
在所有情况下将getline都重定向到var,则不会设置NF(相反,同义,在设置$ 0之后,将设置NF)
1)使用管道
awk 'END{while("who" | getline line > 0) print line}' empty.txt
输出为:
lin :0 2016-11-20 08:57 (:0)
lin pts/0 2016-11-20 09:02 (:0)
2)使用系统
awk 'END{while(system("ls -lh") | getline line > 0) print line}' empty.txt
输出为:
总用量 20K
-rw-rw-r-- 1 lin lin 256 11月 6 17:05 countries
-rw-rw-r-- 1 lin lin 0 11月 19 23:09 empty.txt
-rw-rw-r-- 1 lin lin 35 11月 6 16:53 ip.txt
-rw-rw-r-- 1 lin lin 13 10月 28 22:51 print.sh
-rw-rw-r-- 1 lin lin 29 11月 15 22:40 test.txt
-rw-rw-r-- 1 lin lin 59 11月 9 22:24 worker.txt
本节主要介绍awk操作. 该动作的主要功能是在模式匹配后对数据进行操作.
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-212340-1.html
说白了就是要个面子
多少人丢了这份执着