awk用法总结命令行操作

一些常用的语句:(正常的awk命令跟随-F参数指定分隔符号,如果是空格或tab键就可以省略了。)
1 awk '{print$1}' filename
解释:打印出文件filename的第一列

2 awk 'if($2>20){print $0}' filename
解释: 如果第二列大于20就显示满足条件的行

3 awk '{if($5>20||$2==10){print $1}}' filename
解释: 如果第5列大于20或者第一列等于10的就显示满足条件的第一列的值

4 awk 'BEGIN{print "head\n"}' {print $1} END{"finish"}' filename
解释: 加信息头,输出文件filename的第一列,且输出结束信息

5 awk '{if($3~/china/)print $0}' filename
解释: 假如第四列匹配china这个字符串,则输出满足条件的整行

6 awk '/^china/' filename
解释: 假如行首匹配china,则输出满足条件的整行

7 awk '{print NF,NR,S0} END{pirnt FILENAME}' filename
解释: 输出字段数,记录号,且结束时输出文件名

8 echo $VAR|awk '{print "head\t" $0}'
解释: 在变量VAR之前输出一列head,跳格,再输出整行

9 awk '{if(uin[$1]>$2) uin[$1]=$2;}END{for(i in uin) print i"\t"uin[i]}' xxx.txt > oooo.txt

问题: 第一个字段是QQ号码,第2个是注册时间,如果一个QQ号码多次注册,打印最小注册时间,如果只注册一次,打印该行记录即可,比较急的脚本哪位有什么好办法没有
改进版:awk '{if(uin[$1]>$2 || uin[$1] == ""){uin[$1]=$2}}END{for(i in uin){print i"\t"uin[i]}}' xxx.txt
嗯,确实没有考虑空值情况,打印出来第2个字段是空置 (考虑了第一次赋值)


10 awk '{a[$1]=a[$1]+$2}END{for (i in a) print i,a[i]}' urfile 统计付费

awk '{a[$3]=$0}END{for (i in a) print a[i]}' urfile 去重
awk '{a[$1]=$0}END{for (i in a) print a[i]}' urfile 去重

11 awk '{if(a[$1] != "" && a[$1] < $2){a[$1]=$2};if(a[$1] == ""){a[$1]=$2}}END{for(i in a){print i,a[i]}}' 9.txt >>res-zui.txt
12 awk '{a[$1]=$0}END{for(i in a)print a[i]}' https://www.360docs.net/doc/fa12111683.html,1.txt 第一字段一样的取一行
100002398 2008-10-02 13:54:41 0 2946 2009-07-03 17:42:11
100002398 2010-06-07 20:36:11 0 7272 2011-02-16 18:25:52
100002835 2008-08-25 10:06:59 0 19429 2011-01-20 10:46:20
100005752 2008-06-02 13:09:01 1 154 2009-03-08 08:38:55
100005752 2010-08-11 09:55:33 1 3444 2010-08-18 04:35:29
13 awk '{if($5>a[$1]){a[$1]=$5;b[$1]=$0}}END{for(i in b)print b[i]}' pipo

流失

14 统计本目录下,非目录的文件的总大小
ls -l |awk '$1!~/^d/{tol+=$5}END{print tol}'
ls -l |grep ^- |awk '{tot+=$5}END{print "total:" tot}'

15统计一个文件内任何符号的出现个数
awk '{for(i=1;i<=length($0);i++) ++S[substr($0,i,1)]}END{for(a in S) print S[a],a }' file

16 awk -F: 'BEGIN{OFS='++'}/^PIPPO/{print $1,$2,$3}' /etc/passwd
使用选项-F,指定:为分隔字符,账号pippo的第1-3栏显示出来

使用print 和printf

的区别,printf格式更自由一些,我们可以更加自由的指定要输出的数据,print会自动在行尾给出空格,而printf是需要给定" \n"的,如果感兴趣你可以把“\n”去掉看一下结果。%s代表字符串%d 代表数字,基本上%s都可以处理了因为在文本里一切都可以看成是字符串,不像C语言等其他语言还要区分数字、字符、字符串

17 将文件中所有的字串 "Regular Expression" 或 "Regular expression" 换成 "Regexp"
awk '
{ gsub( /Regular[ \t]+[Ee]xpression/, "Regexp")
print
}
' $*

18 去除文件中的空白行(或仅含空白字符或tab的行)
awk '$0 !~ /^[ \t]*$/ { print }' $*

19 在文件中具有 ddd-dddd (电话号码型态, d 表digital)的字串前加上"TEL : "
awk '
{ gsub( /[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]/, "TEL : &" )
print
}
' $*

20 从文件的 Fullname 中分离出 路径 与 档名
awk '
BEGIN{
Fullname = "/usr/local/bin/xdvi"
match( Fullname, /.*\//)
path = substr(Fullname, 1, RLENGTH-1)
name = substr(Fullname, RLENGTH+1)
print "path :", path," name :",name
}
' $*
结果印出 path : /usr/local/bin name : xdvi

21 将某一数值改以现金表示法表示(整数部分每三位加一撇,且含二位小数)
awk '
BEGIN {
Number = 123456789
Number = sprintf("$%.2f",Number)
while( match(Number,/[0-9][0-9][0-9][0-9]/ ) )
sub(/[0-9][0-9][0-9][.,]/, ",&", Number)
print Number
}
' $* 还没有理解

22 把文件中所有具 "program数字.f"形态的字串改为"[Ref : program数字.c]"
awk '
{
while( match( $0, /program[0-9]+\.f/ ) ){
Replace = "[Ref : " substr( $0, RSTART, RLENGTH-2) ".c]"
sub( /program[0-9]+\.f/, Replace)
}
print
}
' $*

23 awk 'BEGIN{data="p12-P34 P56-p61";while(match(data,/[0-9]+/)>0){print substr(data,RSTART,RLENGTH);sub(/[0-9]+/," ",data)}}'
结果输出“
12
34
56
61

24 首字母变大写
awk '
BEGIN {
upper="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
lower="abcdefghijklmnopqrstuvwxyz"
}
{position=index(lower,substr($0,1,2))
print substr(upper,position,1)substr($0,3)
}'

25 查找与替换
awk 'BEGIN{str="china i love you";sub(/love/,"hate",str); print str}'

26 九九乘法表
awk 'BEGIN{for(i=1;i<=9;i++){for(j=1;j<=9;j++){arr[i,j]=i*j;print i,"*",j"=",arr[i,j]}}}'

27 [chengmo@localhost ~]$ awk 'BEGIN{OFMT="%.3f";print 2/3,123.11111111;}' /etc/passwd
0.667 123.111

28 按宽度指定分隔符(FIELDWIDTHS使用)

[chengmo@localhost ~]$ echo 20100117054932 | awk 'BEGIN{FIELDWIDTHS="4 2 2 2 2 3"}{print $1"-"$2"-"$3,$4":"$5":"$6}'
2010-01-17 05:49:32



FIELDWIDTHS其格式为空格分隔的一串数字,用以对记录进行域的分隔,FIELDWIDTHS="4 2 2 2 2 2"就表示$1宽度是4,$2是2,$3是2 .... 。这个时候会忽略:FS分隔符。

29 获得linux环境变量(ENVIRON使用)

[chengmo@localhost ~]$ awk 'BEGIN{print ENVIRON["PATH"];}' /etc/passwd
/usr/lib/qt-3.3/bin:/usr

/kerberos/bin:/usr/lib/ccache:/usr/lib/icecc/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/java/jdk1.5.0_17/bin:/usr/java/jdk1.5.0_17/jre/bin:/usr/local/mysql/bin:/home/web97/bin

ENVIRON是子典型数组,可以通过对应键值获得它的值

30 输入参数获取(ARGC ,ARGV使用)

[chengmo@localhost ~]$ awk 'BEGIN{FS=":";print "ARGC="ARGC;for(k in ARGV) {print k"="ARGV[k]; }}' /etc/passwd
ARGC=2
0=awk
1=/etc/passwd



ARGC得到所有输入参数个数,ARGV获得输入参数内容,是一个数组

31 获得传入的文件名(FILENAME使用)

[chengmo@localhost ~]$ awk 'BEGIN{FS=":";print FILENAME}{print FILENAME}' /etc/passwd

/etc/passwd

FILENAME,$0-$N,NF 不能使用在BEGIN中,BEGIN中不能获得任何与文件记录操作的变量

32取得SHELL环境变量的值
awk 'BEGIN{for(k in ENVIRON){print k"="ENVIRON[k]}}'


33 性能比较

[chengmo@localhost nginx]# time (awk 'BEGIN{ total=0;for(i=0;i<=10000;i++){total+=i;}print total;}')
50005000

real 0m0.003s
user 0m0.003s
sys 0m0.000s

[chengmo@localhost nginx]# time(total=0;for i in $(seq 10000);do total=$(($total+i));done;echo $total;)
50005000

real 0m0.141s
user 0m0.125s
sys 0m0.008s



实现相同功能,可以看到awk实现的性能是shell的50倍!

34 打印奇数行[root@localhost ~]# seq 10|awk 'i=!i'
1
3
5
7
9
i=!i 当i=0时,!i=1,所以i=1

awk 'i=!i' 就是根据是1还是0来的,是1就打印,是0就不打印

[root@localhost ~]# seq 1 10 | awk 'i=!i;{print i}'
1
1
0
3
1
0
5
1
0
7
1
0
9
1
0
[root@localhost ~]# seq 1 10 | awk 'i=!i'
1
3
5
7
9

相关文档
最新文档