awk 用法:awk ' pattern {action} '
常用变量:
变量名 | 含义 |
ARGC | 命令行变量个数 |
ARGV | 命令行变量数组 |
FILENAME | 当前处理文件名 |
FNR | 当前正在处理文件的第几行 |
FS | 输入数据的分隔符 |
RS | 输入数据的行分隔符 |
NF | 当前记录的记录个数 |
$NF | 当前记录的最后一个参数 |
NR | 到目前为止处理的行数 |
OFS | 输出的字段分隔符 |
ORS | 输出的行分隔符 |
实用例子:
1、awk '/reg/' file 显示文件file中包含reg的匹配行。 awk '$1 == 5' file
awk '$1 == "CT"' file #必须有双引号,否则会被认为是变量
awk '$1 * $2 >100 ' file
awk '$2 >5 && $2<=15' file #直接应用逻辑表达式
2、awk '{print NR,NF,$1,$NF,}' file 显示文件file的当前记录号、域数和每一行的第一个和最后一个域。
awk '/101/ {print $1,$2 + 10}' file #找到有101的行,并输出第一个字段和第二个字段+10,输出分割符默认是空格,可以通过OFS来修改
awk '/101/ {print $1$2}' file #输出的字段中间没有任何分隔符
awk '/101/ {print $1 $2}' file #同上,没有任何分隔符
3、输入数据不同的分隔符。
awk -F "|" '{print $1}' file #按照新的分隔符“|”进行操作。
awk 'BEGIN { FS="[: \t|]" } {print $1,$2,$3}' file #输入分割符同时识别多种,对于冒号、空格、竖线都会进行划分
上面的等价于 awk -F"[: \t|]" '{print $1,$2,$3}' file
4、某个字段符合某种格式
awk '$1 ~ /101/ {print $1}' file 显示文件中第一个域匹配101的行(记录)。
5、修改输出字段分隔符。
awk 'BEGIN { OFS="%"} {print $1,$2}' file #通过设置输出分隔符(OFS="%")修改输出格式。
6、复杂一点的例子
awk 'BEGIN { max=100; print "max=" max} #BEGIN 表示在处理文件内容之前就进行的操作。
{max=($1 >max ?$1:max); print $1,"Now max is "max}' file #取得文件第一个字段和max中最大的值并输出,最后一行输出的就是整个文件的最大值。
#另一个例子:输出一个三目运算表达式的返回值
awk '{print ($1>4 ? "high "$1: "low "$1)}' file
7、awk '$1 * $2 >100 {print $1}' file
首先如果没有{}的内容,会选出满足“$1 * $2 > 100”所有的行;有了{}之后,对于选出来的这些行,只是输出第一个字段。
8、awk '$1 == 'Chi' {$3 = 'China'; print}' file
首先找到有Chi这个字符串的行,然后执行后面的{},将第三个字段赋值为China,然后输出更改后的行。
9、awk '/tom/ {wage=$2+$3; printf wage}' file
除非是逻辑表达式,找到包含某个字符串的行都需要用"/"来包裹。本例中,找到包含tom的行后,新建一个变量为第二个变量和第三个变量的和,然后输出。
10、后处理:
awk '/tom/ {count++;} END {print "tom was found "count" times"}' file
END表示在所有输入行处理完后进行处理,对于包含tom的所有行都进行计数,最后输出数量。
11、替换与输出到文件
awk 'gsub(/\$/,"");gsub(/,/,""); cost+=$4; END {print "The total is $" cost>"filename"}' file
gsub是awk内置函数,/reg/标示一个正则表达式,是gsub的第一个参数,第二个参数是源字符串,即,用源字符串替换正则表达式所匹配的所有字符串。print过程中用大于号">"会将输出重定向到一个以字符串为名字的文件中。 考虑下面这个复杂点的例子,看看它是什么含义,其中printf是更灵活的格式化输出函数。
awk '{gsub(/\$/,"");gsub(/,/,"");
if ($4>1000&&$4<2000) c1+=$4;
else if ($4>2000&&$4<3000) c2+=$4;
else if ($4>3000&&$4<4000) c3+=$4;
else c4+=$4; }
END {printf "c1=[%d];c2=[%d];c3=[%d];c4=[%d]\n",c1,c2,c3,c4}"' file
12、如何终端处理与跳过处理
awk '{gsub(/\$/,"");gsub(/,/,"");
if ($4>3000&&$4<4000) exit;
else c4+=$4; }
END {printf "c1=[%d];c2=[%d];c3=[%d];c4=[%d]\n",c1,c2,c3,c4}"' file
这个例子中用exit标示终止处理,标示不再处理后面的行,但是还是会执行END中的语句。
awk '{gsub(/\$/,"");gsub(/,/,"");
if ($4>3000) next;
else c4+=$4; }
END {printf "c4=[%d]\n",c4}"' file
这个例子中的next和程序设计中的continue是一个意思,表示跳过这行。
13、合并文件
awk '{ print FILENAME,$0 }' file1 file2 file3 > fileall
把file1、file2、file3的文件内容全部写到fileall中,格式为文件名和所有字段。其实过程是依次处理每个文件,用大于号进行重定向。
14、拆分文件
awk ' {print substr($0,index($0," ") +1)>$1}' fileall
将文件拆分,对应于13这个例子,$1是文件名,获得每一行除了文件名的内容后,输出到文件名中。值得注意的是,数据是append的,不会冲掉整个文件,awk还是挺智能的~
index是找到第一个参数(字符串)中,目标字符串(第二个参数)出现的位置。
15、在BEGIN中执行shell命令。
awk 'BEGIN {"date"|getline d; print d}' #通过管道把date的执行结果送给getline,并赋给变量d,然后打印。
awk 'BEGIN {system("echo \"Input your name:\\c\""); getline d;print "\nYour name is",d,"\b!\n"}' #通过system函数来执行shell命令,这里的geline会和用户交互等待输入。
16、循环,类c语言,自己体会一下:)
awk '{ i=1;while(i<NF) {print NF,$i;i++}}' file #通过while语句实现循环。
awk '{ for(i=1;i<NF;i++) {print NF,$i}}' file #通过for语句实现循环。
17、几个应用正则表达式的例子
awk '/^(no|so)/' test #打印所有以模式no或so开头的行。
awk '/^[ns]/{print $1}' test #如果记录以n或s开头,就打印这个记录。
awk '$1 ~/[0-9][0-9]$/(print $1}' test #如果第一个域以两个数字结束就打印这个记录。
awk '/^root/,/^mysql/' test #打印以正则表达式root开头的记录到以正则表达式mysql开头的记录范围内的所有记录。如果找到一个新的正则表达式root开头的记 录,则继续打印直到下一个以正则表达式mysql开头的记录为止,或到文件末尾。