Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1613391
  • 博文数量: 409
  • 博客积分: 6240
  • 博客等级: 准将
  • 技术积分: 4908
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-01 00:04
文章分类

全部博文(409)

文章存档

2021年(1)

2019年(1)

2017年(1)

2016年(13)

2015年(22)

2013年(4)

2012年(240)

2011年(127)

分类:

2011-08-01 13:26:58

原文地址:awk心得笔记 作者:ywlscpl

awk使用过程中一些心得的记录,持续更新
 
1、awk -F '[#, ]+' '{}'   用正则做FS,即以一个或以上的#或空格做FS,值得注意的是也包括两者的任意组合,如下例中d是作为$5的,不是$6,也就是说" # "、" ## "、" #   #"也是FS
 

[root@Mylinux tmp]# echo "1 # a# b ## c # #d" | awk -F '[#, ]+' '{print "$1:"$1"$2:"$2"$3:"$3"$4:"$4"$5:"$5"$6:"$6}'
$1:1$2:a$3:b$4:c$5:d$6:

awk -F '[ \t]+|,' 以任意个空格或TAB或1个,做分割符

2、awk 'var=xx'  awk省略action的写法,默认action就是{print},但稍有特殊,其执行了var=xx的赋值操作,并且用xx作为pattern。

awk 'var=xx'应该说等价于awk 'xx{print}{var=xx}'

awk 'var=xx{cmd}'等价于awk 'xx{cmd}{var=xx}'

(1)、复杂点的例子:awk '!a[$1]++&&NF' 将会打印出字段1第一次出现的行,并且空行去除,并且$1为空的行去除(因为$1为空,a[$1]为空)

即等价于awk 'a[$1]&&NF{print}{a[$1]=a[$1]+1}'

[root@Mylinux tmp]# cat file
1,1
1,2
1,3
2,2

,3
[root@Mylinux tmp]# awk -F "," '!a[$1]++&&NF' file
1,1
2,2

(2)、空行没有打印,因为NF用做了pattern,NF值为0则后面的{print}未执行。

[root@Mylinux tmp]# awk 'NF=NF' file
1,1
1,2
1,3
2,2
,3

(3)、第6行也未打印,因为空行及第6行及的$1为空

[root@Mylinux tmp]# awk -F "," -v OFS="," '$1=$1' file
1,1
1,2
1,3
2,2

(4)、赋值操作完成,0做pattern,action未执行

[root@Mylinux tmp]# awk 'a=0;END{print a}' file                 
0

3、设定OFS后,需对字段数NF(较老的awk版本可能无效)或某字段$1、$2...做过修改后才能生效

[root@Mylinux tmp]# echo "1 2 3" | awk 'BEGIN{OFS=","}1'
1 2 3
[root@Mylinux tmp]# echo "1 2 3" | awk 'BEGIN{OFS=","}NF=NF'
1,2,3
[root@Mylinux tmp]# echo "1 2 3" | awk 'BEGIN{OFS=","}$1=$1'
1,2,3

4、大文件分割:分割大文件file中第n到m行为新文件

注意处理到m行时加个exit退出

awk 'NR>=n&&NR<=m{print;if(NR==m)exit}' file >newfile

5、sub gsub gensub区别

   sub(a,b[,c]) 替换第一次匹配,匹配正则a,用b替换,c为指定替换目标是哪个域如$1,$2,若无c指$0,返回值为替换成功次数

   gsub(a,b[,c]) 全局替换,匹配正则a,用b替换,c为指定替换目标是哪个域如$1,$2,若无c指$0,返回值为替换成功次数

   gensub(a,b,c[,d])全局替换,匹配正则a,用b替换,c为指定替换目标是第几次匹配,d为指定替换目标是哪个域如$1,$2,若无d指$0,返回值为target替换后内容(未替换还是返回target原内容),与sub、gsub不同的是,target内容替换后不改变。

gensub(/123/,"x",1,$1)替换$1中 第一次匹配到的123为字符x,返回值为$1替换后的内容,且$1的内容并没有改变

[root@Mylinux tmp]# echo "a123b a456b" | awk '{print gensub(/a([0-9]*)b/,"\\1",1)}'
123 a456b
[root@Mylinux tmp]# echo "a123b a456b" | awk '{print gensub(/a([0-9]*)b/,"\\1",2)}'
a123b 456

target不会被改变:

[root@Mylinux tmp]# echo "a123b a456b" | awk '{print gensub(/a([0-9]*)b/,"\\1",1,$1);print $1}'
123
a123b

6、split(a,b[,c]) 将字符串a根据分隔符c分割后赋值给数组b,若没有指定c,FS作为分隔符,返回值为分割后域个数

[root@Mylinux ~]# echo "1 2 3" | awk '{print split($0,m)"|"m[1],m[2],m[3]}'
3|1 2 3
[root@Mylinux ~]# echo "1#2#3" | awk '{print split($0,m,"#")"|"m[1],m[2],m[3]}'
3|1 2 3

[root@Mylinux tmp]# echo "1#2#3" | awk '{print m[split($0,m,"#")]}'
3

7、split函数中用正则做分隔符

[root@Mylinux tmp]# echo "1@2##3" | awk '{split($0,m,"#+|@");print m[1],m[2],m[3]}'
1 2 3

8、当用到$0~/ /这种形式,且正则中又需要引用awk变量时,可以这样:

[root@Mylinux tmp]# echo "123 123abc" | awk '$2~"^"$1".*c$"'
123 123abc


阅读(622) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~