awk数组处理两个文件的例子
如果文件a中包含文件b,则将文件b的记录打印出来输出到c文件里
文件a:
10/05766798607,11/20050325191329,29/0.1,14/05766798607
10/05767158557,11/20050325191329,29/0.08,14/05767158557
文件b:
05766798607
05766798608
05766798609
通过文件a和文件b对比,导出这样的文件出来.
10/05766798607,11/20050325191329,29/0.1,14/05766798607
本人查了很多网上的答案都是错误码的
正确答案应该:
方法一: awk -F'[/,]' 'ARGIND==1{a[$0]}ARGIND>1{if ($2 in a)print $0}' b a >c
方法二: awk -F'[/,]' 'NR==FNR{a[$0]}NR>FNR{if ($2 in a) print $0}' b a >c
这两种方法是用数组处理的,速度比较快,处理9万行只需4秒。
还有一种方法是通过while 每次用read 命令从b中读一条记录与a中$2比较如果相等则输出到c中
zlwt]# more for3.sh
#!/bin/bash
while read line ; do
awk -F'[/,]' '$2 == '$line' {print $0}' a >>c
done < b;
这种方法很好理解,但速度非常慢,每次只读取一条记录,9万行需5个小时处理。
例二 awk数组处理两个文件索引的问题(替代法)
[root@TestAs4 zlwt]# more a
deptA
deptB
deptC
deptD
[root@TestAs4 zlwt]# more b
aaa 0
bbb 1
ccc 2
ddd 0
eee 2
fff 2
[root@TestAs4 zlwt]# awk 'NR==FNR {k[i++]=$1} NR>FNR { print $1,k[$2]}' a b
aaa deptA
bbb deptB
ccc deptC
ddd deptA
eee deptC
fff deptC
NR==FNR {k[i++]=$1} #先把a文件的值赋给数组k,下标从0自动增长
NR>FNR { print $1,k[$2] #其中 $1,$2是b中的第一,二个域,k[$2]为a的值
下面方法是r2007版主的其实是一样的
[root@TestAs4 zlwt]# awk '{if(NR==FNR)k[i++]=$0;else print $1,k[$2]}' a b
aaa deptA
bbb deptB
ccc deptC
ddd deptA
eee deptC
fff deptC
另外一个例子
awk ' BEGIN{FS="[|]";OFS="|"}
FNR==NR{a[$1]=$2}
FNRelse {$1=a[$1];print}}
' wj wj1>wj2
文件1
1|name1
2|name2
3|name3
5|name5
6|name6
文件2
1|name11
2|name22
3|name33
4|name44
5|name55
6|name66
7|name77
8|name88
输出结果
name1|name11
name2|name22
name3|name33
13|name44
name5|name55
name6|name66
13|name77
13|name88
它在处理2个以|分割的文件
例如
文件1 wj 格式
id1|desc1
文件2 wj1格式
id2|desc2
FNR==NR{a[$1]=$2} 意思是处理第一个文件时 把 desc1 赋值给 数组 a 的 a[id1] 单元。
FNR{if(!a[$1]) {$1="13";print}
else {$1=a[$1];print
如果a[$1] 是空,就把第2文件那行的第1列替换为 13 输出 如: 13|desc2
如果a[$1]非空,就是这个数组值已经在处理第1文件赋过值。就把$1替换为 a[$1] 即 文件1对应的$2。输出的就是 desc1|desc2
归纳一句 就是在文件2中以id2在文件1中查id1=id2的对应desc1 ,
找到输出 desc1|desc2
找不到输出 13|desc2
例:把数组中如1331131***** 批量替换成861331131*****
#cat a.txt
13994623***
13394660***
13394660***
13394671***
13394672***
13394690***
13394692***
15304863***
#awk '{print "86"$1}' a.txt > b.txt
8613994623***
8613394660***
8613394660***
8613394671***
8613394672***
8613394690***
8613394692***
8615304863***
#awk '{print substr($1,3,11)}' b.txt 把86去掉
13994623***
13394660***
13394660***
13394671***
13394672***
13394690***
13394692***
15304863***
------------------------------------------------------------------------------
两个文件关联处理
[root@TestAs4 cwm]# awk '{print $1}' 153mdn.txt |uniq -c
4 七台河
5 伊春
18 佳木斯
13 双鸭山
66 哈尔滨
1 大兴安岭
32 大庆
20 牡丹江
19 绥化
16 鸡西
15 鹤岗
10 黑河
19 齐齐哈尔
[root@TestAs4 cwm]# awk '{print $1,substr($1,1,7)}' hlj_jifei >hlj_temp
[root@TestAs4 mdn]# more hlj_temp
13009700055 1300970
13009700495 1300970
13009701075 1300970
13009701282 1300970
[root@TestAs4 mdn]# ls
2 3 awk_script cwm hlj_jifei hlj_temp newmdn_table.TXT temp test1
[root@TestAs4 mdn]# more test1
1300019 510 020 广州
1300101 110 010 北京
1300103 110 010 北京
1300104 110 010 北京
1300106 110 010 北京
[root@TestAs4 mdn]# awk 'NR==FNR{a[substr($1,1,7)]=$4}NR>FNR&&a[b=substr($1,1,7)]{print $1,a[b]}' test1 hlj_temp |more
或
[root@TestAs4 mdn]# awk 'NR==FNR{a[$1]=$4}NR>FNR&&a[b=substr($1,1,7)]{print $1,a[b]}' test1 hlj_temp
13009700055 哈尔滨
13009700495 哈尔滨
13009701075 哈尔滨
13009701282 哈尔滨
--------------------------------------------------------------------------------------
[root@TestAs4 mdn]# more temp
1300970 13009700055
1300970 13009700495
1300970 13009701075
1300970 13009701282
--------------------------------------------------------------------------------
[root@TestAs4 mdn]# more awk_script
BEGIN { while ((getline < "test1") > 0){ lines[$1]=$4 };OFS=" " }
{
if($1 in lines){
$1=lines[$1] #把test1文件的$4替换到temp文件的$1上
print $0
}
}
#要求把test1文件的第四个字段插入到temp文件的相应条目的第一个子段中
#利用getline获取test1文件的第四个字段,并且放到一个数组中。
[root@TestAs4 mdn]# ls
2 3 awk_script cwm hlj_jifei hlj_temp newmdn_table.TXT temp test1
[root@TestAs4 mdn]# awk -f awk_script temp |wc -l
63440
[root@TestAs4 mdn]# awk -f awk_script temp |more
哈尔滨 13009700055
哈尔滨 13009700495
awk又一个例子: 统计某一列所有值的和
把所有第二列的值求和
[root@TestAs4 ~]# more cwm.txt
cwm 123
zbl 124
yhh 2
cj 1
[root@TestAs4 ~]# awk '{a[x++]=$2};END{for(i=1; i<=NR; i++) b=b+a[i-1];print b }' cwm.txt
250
[root@TestAs4 ~]# awk '{a[NR]=$2;b=0};END{for(i=1; i<=NR; i++) b=b+a[i];print b }' cwm.txt
250
前面两种方法不可取
awk '{a+=$2}END{print a}' cwm.txt 这种方法最简单
显示文件的从第m行到n行
[root@TestAs4 ~]# sed -n '2,10'p mdn.txt
[root@TestAs4 ~]# awk 'NR==2,NR==10{print $0}' mdn.txt
给手机号码分G网C网
1.C网(C网是133或153开头的号)
awk '$1 ~/^133/ || $1 ~/^153/' file.txt >C网.txt
2.G网(由于G网比较多非133非153开头的都是)
awk '$1 !~/^133/ && $1 !~/^153/' file.txt >G网.txt
统计a字符数
[root@orzz chenwm]# more 1.txt
a a b c a
c a b a a
aa a a a
a b b b
awk '{for(i=1;i<=NF;i++){if($i=="a")b=b+1}print b;b=0 }' 1.txt
3
3
3
1
给两个文件每行对应连接
[root@TestAs4 cwm]# more tep_01.txt
cwm 13911320988
zbl 13931095233
chen 12333333333
cwm 12233333333
cwm 45555555555
[root@TestAs4 cwm]# more tep_02.txt
cwm1 111320988
zbl1 131095233
chen1 133333333
cwm1 133333333
cwm1 455555555
awk 'NR==FNR {a[FNR]=$0} NR>FNR { print $0,a[FNR]}' tep_01.txt tep_02.txt
cwm1 111320988 cwm 13911320988
zbl1 131095233 zbl 13931095233
chen1 133333333 chen 12333333333
cwm1 133333333 cwm 12233333333
cwm1 455555555 cwm 45555555555
还有一个命令 paste
[root@TestAs4 cwm]# paste tep_01.txt tep_02.txt
cwm 13911320988 cwm1 111320988
zbl 13931095233 zbl1 131095233
chen 12333333333 chen1 133333333
cwm 12233333333 cwm1 133333333
cwm 45555555555 cwm1 455555555
awk 处理HAN开头下一个HAN的上一行数字为结尾的文件 ... 或者中提取任一文件段 以HAN开头,下一个HAN的上一行数字段为结尾的一段 生成HAN1等这样的文件
[root@TestAs4 cwm]# more file1.txt
HAN 1
12 23 34 45
23 45 56
HAN 2
12 23 34 45
23 45 56
12 23 34 45
HAN 3
12 23 34 45
23 45 56 44
12 23 34 45
23 45 56
HAN 4
12 23 34 45
23 45 56
HAN n
awk '{ if ($1=="HAN" && NF==2) fn=$2; print $0>>"HAN" fn;}' file1.txt
awk '{fn=$2; print $1 >>fn"hb"}' hbuse.txt 这是所有记录以$2归类。
-----------------------找出两文件相同及不同的值----------------------------------
awk 'NR==FNR{a[$0]++} NR>FNR&&!a[$0]' file1 file2 找出文件2中不同的值
awk 'NR==FNR{a[$0]++} NR>FNR&&a[$0]' file1 file2 找出两文件中相同的值
或
awk 'NR==FNR{a[$0]}NR>FNR{ if(!($1 in a)) print $0}' file1 file2 找出文件2中不同的值
awk 'NR==FNR{a[$0]}NR>FNR{ if($1 in a) print $0}' file1 file2 找出两文件中相同的值
------------------------awk按字段分类统计----------------------------------------
1300018 广东
1300019 广东
1300100 北京
1300101 北京
1300126 北京
1300127 北京
1300128 北京
1300129 北京
1300130 天津
1300131 天津
1300132 天津
1300133 天津
想得到三个文件:
广东2.txt
1300018
1300019
北京6.txt
1300100
1300101
1300126
1300127
1300128
1300129
天津4.txt
1300130
1300131
1300132
1300133
awk '{a[$2]++;print $1 > $2} END {for (i in a) {print "mv " i " " i""a[i]".txt" }}' ufile|sh
==========================================================================
[root@TestAs4 ~]# more 2.txt
苏儿真|Te Amo|天蓝过我的忧郁|爱你的一切|七夕没下雨|闭上眼睛数到三|似曾相恋|当我们不在一起|不
是同路人|十八岁|不爱就拉倒|赢了爱情输了朋友
黄鸿升|鬼混
童丽|忘记你|你在哪里|爱在何方|情逝|矜持|绿袖子|一天一万年|空白|如果云知道|我心永恒|秋意浓|在
恋爱国度留下的伤|说再见
刘美君|Dance Medley|清晨|隔|Man In The Moon|蠢动|赤裸抱月下|Give Me All Your Love, Boy|霓虹鸟
|Medley|富士山下|我估不到|点解 - 刘美君林海峰|Dance Medley1|So Sad - 刘美君草蜢|依依|你说是甜
我说苦|偷窥 - 刘美君苏永康|这双眼只望你|夜已变得骚了|事后|最后一夜|浮花|午夜情|一见钟情|最后
一夜 (Ballad Version)|最后一夜 (Studio Ballad Version) (Bonus Track)
熊宝贝乐团|营火|灰色
[root@TestAs4 ~]# awk -F"[|]" '{for(i=2;i<=NF;i++){$i=$i" "$1;printf"%s\n",$i}}' 2.txt
Te Amo 苏儿真
天蓝过我的忧郁 苏儿真
爱你的一切 苏儿真
七夕没下雨 苏儿真
闭上眼睛数到三 苏儿真
似曾相恋 苏儿真
当我们不在一起 苏儿真
不是同路人 苏儿真
十八岁 苏儿真
不爱就拉倒 苏儿真
赢了爱情输了朋友 苏儿真
鬼混 黄鸿升
忘记你 童丽
你在哪里 童丽
爱在何方 童丽
情逝 童丽
这个也可以
[root@TestAs4 ~]# awk -F"[#|]+" '{for (i=2;i<=NF;i++) print $i,$1}' 2.txt
==============================================================================
文件如下:
beijing 0100 01234 12233
02 zhejiang 0570
tianjing shandong 0288 8777
siquang jiling heilongjian 5678
用awk 怎么得到以下数据(取最后一个域连续的数字,去掉字符)如下:
0100 01234 12233
0570
0288 8777
5678
方法一: grep -Eo '[0-9 ]+$'
方法二: awk也可以,就是代码长点:
awk '{a="";for(i=NF;i>0;i--){if($i!~/^[0-9]+$/) break;a=$i" "a};print a}'
方法三:用个sed的:
sed -r 's/ ([0-9 ]+$)/\n\1/;s/.*\n *//'
================================================
文本如下:
金迪[jindi] : com.imaginechina.webapp.user.DownLoadAction
path : /downLoad
time : Wed Aug 13 12:10:51 CST 2008
ip:211.99.143.152
[imageid] : is_is138_063
[imageType] : CrtvImage
------------------------------------------------------------------------------------
吴亮[wuliang] : com.imaginechina.webapp.user.DownLoadAction
path : /downLoad
time : Wed Aug 13 12:12:08 CST 2008
ip:213.14.33.11
[imageid] : 20080813_21127
[imageType] : NewsImage
------------------------------------------------------------------------------------
金迪[jindi] : com.imaginechina.webapp.user.DownLoadAction
path : /downLoad
time : Wed Aug 13 12:12:16 CST 2008
ip:211.99.143.152
[imageType] : CrtvImage
[imageid] : is_ie248_002
查找ip地址不是213.14.33.11然后把该段信息打印出来
比如上面3段应该打印出
金迪[jindi] : com.imaginechina.webapp.user.DownLoadAction
path : /downLoad
time : Wed Aug 13 12:10:51 CST 2008
ip:211.99.143.152
[imageid] : is_is138_063
[imageType] : CrtvImage
------------------------------------------------------------------------------------
金迪[jindi] : com.imaginechina.webapp.user.DownLoadAction
path : /downLoad
time : Wed Aug 13 12:12:16 CST 2008
ip:211.99.143.152
[imageType] : CrtvImage
[imageid] : is_ie248_002
用awk解决:
awk -v RS="-\n" '!/213\.14\.33\.11/' urfile
===========================================================================
如果第二个域 前一行的值大于后一行就记录下来,最后一行也记录下来,然后输出 ,请教,上面这个如何弄
要是再加个条件,前面行的数一样的时候就做这个操作,该怎么写awk呢
[root@orzz cwm]# more t.txt
1 97
1 4
1 0
1 1000
1 0
1 150
1 16
2 263
2 123
2 336
2 25
[root@orzz cwm]# awk '{a[NR]=$2;b[NR]=$0;c[NR]=$1};END{for(i=1; i<=NR; i++) if((a[i]>a[i+1])||(c[i]!=c[i+1]))print b[i]}' t.txt
1 97
1 4
1 1000
1 150
1 16
2 263
2 336
2 25
==============================================================================
打印中间行 如果是偶数行就打印 总行数/2 如果是奇数行 就打印 (总行数+1)/2
awk '{a[NR]=$0}END{for(i in a);{if(NR%2==1) {print a[(NR+1)/2]}else{print a[NR/2]}}}' ttt.txt
从中间行到最后 打印出来
awk '{a[NR]=$0}END{for(i in a);{if(NR%2==1) {for(m=(NR+1)/2;m<=NR;m++) print a[m]}else{for(m=NR/2;m<=NR;m++)print a[m]}}}' urfile
awk '{a[NR]=$0}END{if(NR%2==1){for(m=(NR+1)/2;m<=NR;m++) print a[m]}else{for(m=NR/2;m<=NR;m++)print a[m]}}' ttt.txt 这个更简洁一点
===============================================================================
woyunFSF
1qwerqwerwerqwerwe
1rewrdfsdfsdfsdfsdfsdf
1dfgdfgdfgdfgdfgfggdfg
woyunADFSDF
2bfgertwertwertwertw
2rerbpojgopjfgohjfgkfl
2dfgdfgkjlsdfjglkjsfgjkj
woyunSDFAAF
3sdjfsakdjflkasjdfklasd
3lksdjflasjdfkajsdlfjasdl
3sdofiuoasidufoufsoadi
woyunFDSAF
4sdfsadfksdfkjasdfkjkjk
4sdfsadkfjskadjfsfjkdjfk
4sdfkjsdlkfjsdkjfakdsjfjf
输出到文件名woyunFSF ,woyunADFSDF,woyunSDFAAF,woyunFDSAF 相应的下面的行
方法越多越好,思路也ok
[root@orzz cwm]# awk '{if(/woyun/){i=$0}else{print $0 >i}}' tt.txt 能解决问题
========================================================================
如何找出文件中上行以a结束,下一行以b开头,并在b所在行的末尾添加a
***a
b***
改成
***a
b***a
[root@test ~]# more 1
d2222a
k1111
1111a
b1111
22222
b3333
4444a
b8888
[root@test ~]# awk 'BEGIN{FS="\n";RS="";OFS="\n"} {for(i=1;i<=NF;i++) if($i~/a$/ && $(i+1)~/^b/)print $i,$(i+1)"a"}' 1
1111a
b1111a
4444a
b8888a
=====================================================================
找出最大值与最小值
[root@orzz root]# more 2
483
429
411
40
2
1398
792
2
[root@orzz root]# awk 'NR==1{max=min=$1}{if($1>max)max=$1;if($1=1) min=$1}END{print max,min}' 2
[root@gfs1 ~]# more 2.txt
8/10
4/8
1/3
2/5
3/7
6/9
3/6
2/4
10/11
1/2
[root@gfs1 ~]# awk -F/ 'NR==FNR{a[$2]=$0}NR>FNR{while ($1 in a) sub("^"$1,a[$1]);print}' 2.txt 2.txt
1/2/4/8/10
1/2/4/8
1/3
1/2/5
1/3/7
1/3/6/9
1/3/6
1/2/4
1/2/4/8/10/11
1/2
[root@gfs1 ~]#
1398 2
=============================================================
date命令和strftime函数,扩展clock、hwclock
date命令:print or set the system date and time
strftime函数:awk调用了类型为time_t的c函数库 strftime([format [, timestamp]])
功能:Formats timestamp according to the specification in format.
systime函数:同上,Returns the current time of day as the number of seconds since the Epoch systime()
譬如:毫秒级时间戳->格式化时间:echo 12879350 | awk '{print strftime("%F %T", $0)}'
格式化时间->毫秒级时间戳:date -s把当前时间设置成special time,然后 awk '{print systime()}'即可
========================================================================
如果是gawk的话,它有特定的时间函数
- awk -F '[: ]+' '{print mktime("2007 1 1 "$4" "$5" "$6)-mktime("2007 1 1 "$1" "$2" "$3)}'
复制代码
mktime("年 月 日 时 分 秒") 返回指定时间与1970-1-1 00:00:00 之间相差的秒数
或者不用时间函数,因为它是 时:分:秒的形式
- awk -F '[: ]+' '{print ($4*3600+$5*60+$6)-($1*3600+$2*60+$3)}'
复制代码
这样也能够计算差值
[root@gw1 ~]# cat 1.txt
2005 04 01 12 13 32,2005 04 01 12 13 53
[root@gw1 ~]# awk -F, '{print mktime($1)-mktime($2)}' 1.txt
-21
[root@gw1 ~]#
以下是ywlscpl老大写的
- ywlscpl@ubuntu:~$ cat file
- $$callid=1303377714104-9470 $$thread=[http-99-Processor23] $$host=20.1.83.67 $$userid=root $$ts=2011-04-21 17:27:11 $$remotecall=[accountmanage] $$debuglevel=ERROR $$msg=
- $$callid=1303377714104-9470 $$thread=[http-99-Processor23] $$host=20.1.83.67 $$userid=root $$ts=2011-04-21 19:27:11 $$remotecall=[accountmanage] $$debuglevel=ERROR $$msg=
- $$callid=1303377714104-9470 $$thread=[http-99-Processor23] $$host=20.1.83.67 $$userid=root $$ts=2011-04-22 17:27:11 $$remotecall=[accountmanage] $$debuglevel=ERROR $$msg=
- $$callid=1303377714104-9470 $$thread=[http-99-Processor23] $$host=20.1.83.67 $$userid=root $$ts=2011-04-23 17:27:11 $$remotecall=[accountmanage] $$debuglevel=ERROR $$msg=
- ywlscpl@ubuntu:~$ start="2011 04 21 17 27 11"
- ywlscpl@ubuntu:~$ end="2011 04 22 18 00 00"
- ywlscpl@ubuntu:~$ awk -F '\\$\\$ts=' -v s="$start" -v e="$end" '{t=substr($2,1,19);gsub(/[-:]/," ",t)}mktime(t)>=mktime(s)&&mktime(t)<=mktime(e)' file
- $$callid=1303377714104-9470 $$thread=[http-99-Processor23] $$host=20.1.83.67 $$userid=root $$ts=2011-04-21 17:27:11 $$remotecall=[accountmanage] $$debuglevel=ERROR $$msg=
- $$callid=1303377714104-9470 $$thread=[http-99-Processor23] $$host=20.1.83.67 $$userid=root $$ts=2011-04-21 19:27:11 $$remotecall=[accountmanage] $$debuglevel=ERROR $$msg=
- $$callid=1303377714104-9470 $$thread=[http-99-Processor23] $$host=20.1.83.67 $$userid=root $$ts=2011-04-22 17:27:11 $$remotecall=[accountmanage] $$debuglevel=ERROR $$msg=
- ywlscpl@ubuntu:~$
-----------------------------------
反算流量(流量是第10列)
for i in `seq -w 0 23` ;do echo -en "time 2011-06-26:$i\t" ; awk '/26\/Jun\/2011:'"$i"'/{i=i+$10}END{print i/(1024*1024*8)}' st.media.dilian.log ;done
以下是只用awk来完成,不用再循环命令
[root@st01 nginx]# awk '{a[substr($4,9,7)]=a[substr($4,9,7)]+$10}END{for(i in a)print i,a[i]/1000/1000"M"}' fm.kxting.log |sort -k1n
时间 流量
2011:00 28156.4M
2011:01 15397.8M
2011:02 8935.11M
2011:03 6295.14M
2011:04 5137.75M
2011:05 4537.71M
2011:06 7082.36M
2011:07 13592.6M
2011:08 30327.9M
2011:09 41675.7M
2011:10 45973.5M
2011:11 49983.7M
2011:12 49701.5M
2011:13 51606.9M
2011:14 51199.6M
2011:15 1921.09M
每小时的平均流量:
[root@st01 nginx]# awk '{a[substr($4,9,7)]=a[substr($4,9,7)]+$10}END{for(i in a)print i,a[i]*8/3600000000"M/s"}' fm.kxting.log |sort -k1n
2011:00 62.5697M/s
2011:01 34.2174M/s
2011:02 19.8558M/s
2011:03 13.9892M/s
2011:04 11.4172M/s
2011:05 10.0838M/s
2011:06 15.7386M/s
2011:07 30.2059M/s
2011:08 67.3954M/s
2011:09 92.6126M/s
2011:10 102.163M/s
2011:11 111.075M/s
2011:12 110.448M/s
2011:13 114.682M/s
2011:14 113.777M/s
2011:15 71.7846M/s
[root@njsquid1 squid_img]# zcat access.log.12.gz |more
1314061201.528 0 127.0.0.1 TCP_MEM_HIT/200 11609 GET - NONE/- image/jpeg
zcat access.log.12.gz |awk '$1=strftime("%F %T ", $1){print $0}'|more
2011-08-23 09:00:01 0 127.0.0.1 TCP_MEM_HIT/200 11609