Chinaunix首页 | 论坛 | 博客
  • 博客访问: 162343
  • 博文数量: 21
  • 博客积分: 2371
  • 博客等级: 大尉
  • 技术积分: 217
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-15 18:36
文章分类

全部博文(21)

文章存档

2010年(6)

2009年(15)

分类:

2009-02-08 14:13:34

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


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

linux_kaige2011-11-18 23:18:31

兄弟awk还不错啊,学习!
冒昧提个建议啊,echo "1 # a# b ## c # #d" | awk -F '[#, ]+' '{print "$1:"$1"$2:"$2"$3:"$3"$4:"$4"$5:"$5"$6:"$6}'
这个可以echo "1 # a# b ## c # #d" | awk -F '[#, ]+' ‘{$1=$1;print $0}’
如果要加那个$1...$5, echo "1 # a# b ## c # #d" | awk -F '[#, ]+' '{$1=$1}{for(i=1;i<6;i++)printf "$"i" "}{print "\n"$0}' ,对于我写的这个第二个,并不见得简单。。。最近比较忙,好久没来cu了,今晚随便看了下,学习了下兄弟的那个awk

l_penny2010-06-10 16:48:46

帅哥,能留个qq号吗,我是awk初学者

bbgg19832010-04-26 20:42:08

向你学习