這里收集了平時awk的一些問題:
awk的基本功能是對文件進行指定規則瀏覽和抽取信息。
基本格式:
(1) awk [-F 分隔域] 'command' input-file(s)
(2) 寫入shell腳本中
(3) awk -f awk-script-file input-file(s)
注意:這里如果使用if等編程語句,要用{}括起來。
test
name grade score id
hover 2 96 2003073
twq 3 91 2003074
zsm 4 92 2003075
hzm 5 95 2003076
bl 6 96 2003077
1,文本過濾處理:
(1) awk '{print $0}' test #打印文件的全部內容
注意:這里awk使用函數print用來打印整個文件的內容。其中的$0就表示整個文件的內容。
(2) awk '{print $1}' test #抽取文件test中的第一列
注意:如果awk沒有使用-F指定分隔符號,默認的分隔符號是空格和TAB鍵。
#列出所有的用戶名和登陸的shell名
awk -F : '{print $1,$6}' /etc/passwd
(3) awk -F : '$1=="root" {print $0}' /etc/passwd
指打印用戶名為root的那一行
2,文本格式定制
(1)給輸出信息加上表頭
awk -F : 'BEGIN {print "name shell\n--------------------------------"}
{print $!"\t"$6}' /etc/passwd
(2)
awk -F : 'BEGIN {print "name shell\n--------------------------------"}
{print $!"\t"$6} END {"end-of-report"}' /etc/passwd
3,在awk中使用正則表達式
^ 表示匹配行首的字符
[...] 匹配[]正的任意一個字符
(str1|str2) 匹配含有str1或str2的行
. 匹配任意一個字符
(1)匹配
為使一域匹配一正則表達式,可以使用以下兩種方法:
1)$n~正則表達式
2)if($n~正則表示式) print $0
awk -F: '$0 ~ /^root/' /etc/passwd #打印以root開頭的行
awk -F: '{if($0 ~ /^root/) print $0}' /etc/passwd #和上一句等效
*精確匹配*
#打印名字為root的用戶在/etc/passwd文件中的記錄
awk -F : '$1=="root" {print $0}' /etc/passwd
#打印路徑為/root的用戶在/etc/passwd中的記錄
awk -F : '$6=="\/root" {print $0}' /etc/passwd
4,在awk中使用條件操作符
< 小於 >= 大於等於
<= 小於等於 ~ 匹配正則表達式
== 等於 !~ 不匹配正則表達式
!= 不等於
(1)模糊匹配
i)使用if {if($1~/zhengxh/) print $0}
ii)不用if '$0 ~ /zhengxh/'
ex
awk '$0~/zhengxh/' filename
或awk '{if($0~/zhengxh/) print $0} filename #輸出含有zhengxh的行
或awk '/zhengxh/' filename
(2)精確匹配
$n=="chars"
awk '$1=="zhengxh" {print $0}' filename #輸出第一列等於zhengxh的行
(3)反向匹配
$n !~ /adf/
awk '$1 !~ /zhengxh/ {print $0}' filename #輸出第一列不是zhengxh的行
(4)大小寫匹配
awk '/[zZ]hengxh/' filename #匹配含有zhengxh 或是Zhengxh的字符串
(5)使用或運算
awk '$0 ~ /(zhengxh|hover)/' filename #查找含有zhengxh或hover字串的行
或awk '{if($0~/zhengxh/ OR $0~/hover/) print $0}' filename
(6)內置變量
ARGC 命令行參數個數
ARGV 命令行參數排列
ENVIRON 環境變量支持隊列的
FNR 瀏覽文件的記錄數
FS 設置輸入域分隔符,與-F同
NF 記錄域的個數
NR 已讀的記錄數
OFS 輸出域分隔符
ORS 輸出記錄分隔符
RS 控制記錄分隔符
awk 的具體運用(FAQ)
* 把一個文件中滿足條件的放到一個文件不滿足條件的放到另一個文件
awk -F: '{if(NF==6) print $0 > "yes" else print $0 > "no" }' filename
*如何在awk中使用變量
要注意的是在awk中的表達式一般是用''號括起來的,在shell中單引號是全屏蔽符,所以用單引號使得變量無法生效,在使用shell變量時,可以這樣使用
##########################
#/bin/sh
#
name="zhengxh"
count=`awk -F: '
/'${name}'/{ #這里需要使用變量的地方把變量隔開
sum+=$3
}
END { print sum }
'`
*使用awk輸出文件的倒數第N行
tail -n $N $filename | awk '{if(NR==1) print $0}'
*)如何在AWK中使用外部變量
1)aa="aaaaaaa"
awk '{print "'"${aa}"'"}' $filename
2)
以下使用外部變量時有錯:
#!/bin/bash
filepath=/etc/passwd
user=root
result=`awk -F":" '/$user/ { print $1}' $filepath`
echo $result
$
改正:
awk -F':' '/'"$user"'/{print $1}' $filepath
*如何把AWK中的值,傳送到外部的SHELL變量
使用$() 或 ``
aa=`awk -F: '{print $0}' $filename`
*進行統計
文件aa.txt
一個用戶可能有多個記錄,這時只統計一次:
數據 用戶ID 下載文件名稱 用戶所在地 等。。。。。
20071128,0001,1,null,600571021800,028
20071128,0002,1,null,600571001800,021
20071128,0002,1,null,600571001802,021
20071128,0003,1,null,600571031800,020
20071128,0004,1,null,600571001800,010
統計各個的號碼(最后一個字段)數量
awk -F, '{if(!b[$2$6]){a[$6]++;b[$2$6]++}}END{for(i in a){print i,a[i]}}'
*如何把多個語句放在一句話(一行)中處理
cat "$file" | awk '{ip=$1; i=index($0,"\google"); if(i>1){ua = substr($0,i); print ip "\t" ua}}'
*把記錄
aa,bb,cc [name, address, age]
變成記錄
ip,aa,bb,cc [ip,name,address,age]
awk -F, '{pirntf "\"192.168.5.154\","$0}'
*取一個字符串的首字母
str=abc
echo ${str:0:1}
echo $str|awk '{print substr($0,1,1)}'
echo $str|sed 's/\(.\).*/\1/'
*如何在一字符串的前面加上字符串 addtext
awk '{print "addtext \""$0"\""}' temp
*計算不重復的列的總和
aa|001|23
ac|001|23
bb|002|213
cc|004|32
dd|005|34
awk -F'|' '!a[$1]++{sum+=$3} END{print sum} ' filename
*定義多個分界符
aa cc dd
bb,ee ff
awk -F'[ ,]' '{print $3}' filename
有時候有可能出現多個分隔符號,但是我們需要把它當成一個,這時就要用:
***
#echo "adf::adf:f" | awk -F'[:]+' '{print $2}'
#adf
***
#echo "adf::adf:f" | awk -F':' '{print $2}'
# #輸出空
***
*如何用awk處理這樣的文件格式?
源文件格式:
表1313
客戶經理業績情況表(月報表)
支局所名稱:XXXX儲蓄所 月份:10
客戶經理
業績(累計日積數)
酬金
姓名 代號 活期 整整3月
整整6月 整整1年 整整2年 整整3年
整整5年 整整8年 零整1年 零整3年
零整5年 定活兩便
蘭 37040576 0.00 0.00 0.00
0.00 0.00 0.00 0.00
0.00 0.00 0.00 21340.00
0.00 0.00
禚樹征 37040585 27277.21 120.00 0.00
2965.22 0.00 0.00 0.00
0.00 0.00 0.00 0.00
0.00 845615151469035520.00
秦 37040502 20094.30 0.00 0.00
0.00 0.00 0.00 0.00
0.00 0.00 0.00 0.00
0.00 622937933443235840.00
合 計 444868.41 0.00 0.00
2965.22 0.00 0.00 10764.20
0.00 0.00 0.00 0.00
18600.00 13791245122257916000.00
如何用awk處理成以下格式(只要里面的記錄並用逗號分割每個字段,最后一個字段不要,表頭和表尾不要):
"蘭",37040576,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,21340.00,0.00
"禚樹征",37040585,27277.21,120.00,0.00,2965.22,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
"秦",37040502,20094.30,0.00,0.00,0.00,0.00,0.00,,0.00,0.00,0.00,0.00,0.00,0.00
awk '{sub("[ \t]", ","); print $0}' temp
awk '{sub("[ ,\t]", ","); print $0}' temp
*如何用TAB做分隔符號
awk -F'\t'
awk -F'[ \t]' #默認是這樣,以空格或TAB做分隔符
一般模式:awk -F'rexp' '{}' filename
這里rexp是一個正則表達式,用來指示要使用的分隔符。
*--------------------------
在awk腳本中有下面一段
BEGIN{split("123#456#789",team,"#")}
END{for(i in team) print team}
預測的輸出應該是
123
456
789
啊!
為什么實際的輸出是
456
789
123
呢?
答:
---
while(++i in team) print team[i]
----------------------------
*-awk中使用system()
answer:
ls | awk '{if (system("ls " $0) == 0) {print "file " $0 " exists !"}}'
*-調用外部命令和awk結合
使用getline得到外部命令的輸入f
ls | awk '{getline ll; print $ll}'
--------------------------
*-只輸出第一行的內容
awk '{print; exit}'
*-多shell命令
awk ’BEGIN{while("dir|sed 1,3!d"|getline)print $1}‘
*-在awk的輸出中加單引號
#cat file
rwxrwsrwx gprs 512 GPRS
awk '{printf("%s %s '"'%s'"' %s\n",$1,$2,$3,$4)}' file
在這里要理解的是:上面的表達式分成了三塊,前面的''內的內容是一塊,中間的雙引號內的內容是一塊,最后的單引號里的內容是一塊;由於單引號在雙引號中的作用被屏蔽,所以輸出的變量會帶上單引號。從而達到預定結果。
*-得到df -h 顯示出來的百分數字(去掉百分號)
(1)df -h | awk '{if(NR!=1) print $5}' | cut -d% -f 1
(2)df -h | awk -F'[ \t%]+' '{if(NR!=1) print $5}'
***
實現加和
中間結果如下所示:
CPU usr sys idl
0 13 4 76
1 9 4 79
要想顯示下列結果:
1 22 8 155
***
cat data | awk '{if(NR!=1) a+=$1;b+=$2;c+=$3} END{print a,b,c,d,e}'
***
如何實現以幾個字母中任意一個打頭的字符串的查找
cat data
Mike Harrington:(510) 548-1278:250:100:175
Christian Dobbins:(408) 538-2358:155:90:201
Susan Dalsass:(206) 654-6279:250:60:50
Archie McNichol:(206) 548-1348:250:100:175
Jody Savage:(206) 548-1278:15:188:150
Guy Quigley:(916) 343-6410:250:100:175
Dan Savage:(406) 298-7744:450:300:275
Nancy McNeil:(206) 548-1278:250:80:75
John Goldenrod:(916) 348-4278:250:100:175
Chet Main:(510) 548-5258:50:95:135
Tom Savage:(408) 926-3456:250:168:200
Elizabeth Stachelin:(916) 440-1763:175:75:300
awk -F'[ :]' '$1~/^[MJ] {print $1}'
輸出以D開頭的域
awk -F':' '{for(i=1;i<=NF;i++) if($i~/^D/) print $i}' data2
****每一行的和
統計
#cat ab
a 1
a 2
b 2
awk '{a[$1]+=$2} END{for(i in a) print i,a[i]}' file
-----------------------------------
*對兩個文件的處理
----------
大家好,想請教一個問題,我現在有兩個文件,如下所示,這兩個文件格式都是一樣的。我想首先把文件2的第五列刪除,然后用文件2的第一列減去文件一的第一列,把所得的結果對應的貼到原來第五列的位置,請問這個腳本該怎么編寫?
file1:
50.481 64.634 40.573 1.00 0.00
51.877 65.004 40.226 1.00 0.00
52.258 64.681 39.113 1.00 0.00
52.418 65.846 40.925 1.00 0.00
49.515 65.641 40.554 1.00 0.00
49.802 66.666 40.358 1.00 0.00
48.176 65.344 40.766 1.00 0.00
47.428 66.127 40.732 1.00 0.00
51.087 62.165 40.940 1.00 0.00
52.289 62.334 40.897 1.00 0.00
file2:
48.420 62.001 41.252 1.00 0.00
45.555 61.598 41.361 1.00 0.00
45.815 61.402 40.325 1.00 0.00
44.873 60.641 42.111 1.00 0.00
44.617 59.688 41.648 1.00 0.00
44.500 60.911 43.433 1.00 0.00
43.691 59.887 44.228 1.00 0.00
43.980 58.629 43.859 1.00 0.00
42.372 60.069 44.032 1.00 0.00
43.914 59.977 45.551 1.00 0.00
--答--
awk 'NR==FNR{a[NR]=$1}NR!=FNR{$5=a[FNR]-$1;print}' file2 file1
說明:
當NR==FNR時,是第一個文件,到了第二個文件時FNR會從0開始計數,而NR卻繼續在原來的基礎上自增。
先把第一個文件中要使用的內容保存到一個數組中,然后在處理第二個文件時才使用。
這里包含了很好的處理多個文件的方法,值得借鑒。
-------------------------------------------------
**
源文件如下:
37123456,123456789,601234020200051640,"孔霞","03",123456789,"2008/01/06",1,4000,5060.41
37123456,123456789,601234020200062521,"栗汝禮","03",123456010,"2008/01/06",1,100,110.91
37123456,123456789,601234020200069800,"柯純龍","03",370786017,"2008/01/06",1,20000,19500
37123456,123456789,601234020200069800,"柯純龍","03",123456030,"2008/01/06",1,31000,500
37123456,123456789,601234020200068018,"嚴鳳書","03",123456789,"2008/01/06",2,50000,100163.39
37123456,123456789,601234020200070039,"劉慶","03",123456789,"2008/01/06",2,4000,8000
37123456,123456789,601234020200060554,"王蘭英","03",123456789,"2008/01/06",1,1600,91.26
37123456,123456789,601234020200070039,"劉慶","03",123456789,"2008/01/06",2,4000,4000
37123456,123456789,601234020200067710,"羅有艷","03",123456789,"2008/01/06",2,3000,12012.01
37123456,123456789,601234020200064742,"孫祥婷","03",123456789,"2008/01/06",1,50,12.61
37123456,123456789,601234020200069800,"柯純龍","03",123456030,"2008/01/06",1,200,300
37123456,123456789,601234020200060554,"王蘭英","03",123456789,"2008/01/06",1,1000,1091.26
處理要求如下:
如果第三列中的數據是唯一的,就保留這一行,如果有重復的,就保留最后一個記錄行。
--------答---------
awk -F, '{a[$3]=$0}END{for( i in a)print a[i]}' urfile
------------------------------
*如何快速獲取特定字符串的前2(n)行和后2(n)行
$cat file
put 8
put 9
put 10
abc
put 11
put 12
put 13
put 14
abc
put 15
put 16
put 17
put 18
abc
put 19
put 20
put 21
put 22
put 23
abc
put 24
put 25
put 26
put 27
abc
put 28
put 29
put 30
put 31
put 32
abc
put 33
put 34
put 35
put 36
put 37
$ awk '{a[NR]=$0}/abc/{for(i=2;i>=0;i--) print a[NR-i];for(j=1;j<=2;j++){if(!getline) exit;print}print ""}' urfile
小結:
(1)這里使用了數組的功能,數組在作為緩存是普遍用法,要記住。
但這里如果文件超大的話,緩沖區的負擔太大,應換存自己需要的哪些行(這里我只換存了4行)
$ awk '{a[NR%4]=$0}/abc/{for(i=2;i>=0;i--) print a[(NR-i)%4];for(j=1;j<=2;j++){if(!getline) exit;print}print ""}' urfile
(2)使用了getline函數-- $ man awk 就知道,getline函數的作用是: 1)讀取下一行2)set $0
注意這兩個元素的應用.
*)如何提取aaaa12123adsf adfadfbbbb 的aaaa和bbbb中間的內容
$cat file
adfaaaaadfadfadfdfadabbbb
adfaaaaadf ad323452 adfadfdfadabbbbz
$
1)sed -e 's/.*\(aaaa\)\(.*\)\(bbbb\).*/\2/g' file
2)sed -e 's/.*\(a\{3\}\)\(.*\)\(b\{3\}\).*/\2/g' file
3)echo "aaaa121312dfadfbbbbb" | awk -F'aaaa|bbbb' '{print $2}'
*)我以如下字符要處理
a 123
b 124
c 125
a 126
d 127
e 128
ac 129
如果第一列出現兩次或兩次以上將其打印出來,並計算出現次數。
$ awk '{a[$1]++;} END{for(i in a) if(a[i]>=2) {print i,a[i]}}' file
分析: 由以上的命令可以得到流程:
a["a"] 2
a["b"] 1
a["c"] 1
a["d"] 1
a["e"] 1
a["ac"] 1
而for(i in a) 則是要遍歷的i的值是:a,b,c,d,e,ac
*)去掉重復的行
awk '!a[$0]++' file
*)去掉重復行,並保持順序不變
awk 'f[$0]!=1{print;f[$0]=1}'
*)打印重復行
1)awk '{a[$0]++} END{for(i in a) {if(a[i]>1){print i}}}' filename
2)sort cc | uniq -dc
*)如何匹配多個模式
1)awk '/p1|p2/' file
2)awk '/zhengxh|\<root\>' file
*)設定字段分隔符
1)awk -F':' '{OFS="-"}{print $1,$2,$3}' file
*)范圍查找
1)awk -F':' '/20080501[2-9]/' file
*)數字計算求和 file:
hammers QTY: 5 PRICE: 7.99 TOTAL: 39.95
drills QTY: 2 PRICE: 29.99 TOTAL: 59.98
punches QTY: 7 PRICE: 3.59 TOTAL: 25.13
drifts QTY: 2 PRICE: 4.09 TOTAL: 8.18
bits QTY: 55 PRICE: 1.19 TOTAL: 65.45
saws QTY: 123 PRICE: 14.99 TOTAL: 1843.77
nails QTY: 800 PRICE: .19 TOTAL: 152
screws QTY: 80 PRICE: .29 TOTAL: 23.2
brads QTY: 100 PRICE: .24 TOTAL: 24
1)awk '{x=x+$2}' file
*)
---
3 0.022913642968727541
2 0.022706007307485104
2 0.50444767354650166
3 0.022128299612739447
6 0.025468440060252208
1 0.022856042968727539
第一列相同則第二列對應值求和。。。輸出$1,sum
---
1)awk '{a[$1]=+$2; b["2"$1]++} END{for(i in a) if(b["2"i]>1) print i,a[i]}' file
*)我以如下字符要處理
a 123
b 124
c 125
a 126
d 127
e 128
ac 129
如果第一列出現 兩次或兩次以上 將其打印出來,並計算出現次數。
1)awk '{a[$1]++} END{for(i in a) print i,a[i]}' file
------
*)awk中如何顯示大數據
1)awk '{printf"%.f\n", NR + 1211439408282}' filename
*)awk使用外部變量
1)awk '{if($3=="'$a'") print $1,$2,"'$b'",$4}' text
2)awk '{if($3=='\"$a\"') print $1,$2,'\"$b\"',$4}' text
*)
文件內容:
74683 1001
74683 1002
74683 1011
74684 1000
74684 1001
74684 1002
74685 1001
74685 1011
74686 1000
....
100085 1000
100085 1001
文件就兩列,希望處理成
74683 1001 1002 1011
74684 1000 1001 1002
...
就是只要第一列數字相同, 就把他們的第二列放一行上,中間空格分開
--------------
1) awk '{a[$1]=sprintf("%s %s", a[$1],$2)} END{for(i in a) print i,a[i]}' file
2) awk '{a[$1]=a[$1]" "$2} END{for(i in a)print i,a[i]}' data13
*)
76523 1001 1002
76524 1002 1003
76526 1000 1003
76528 1000
....
100025 1000 1025
請教下, 文件第一列已按大小排序, 現在想按第一列的順序, 把沒有出現的行數補上
實現
76523 1001 1002
76524 1002 1003
76525
76526 1000 1003
76527
76528 1000
....
100025 1000 1025
怎樣能夠直接補上這些缺失的行
-------------------
1)???????
*)
每個字段形如 <data name="CYRSBH" value="320400725220211"/>,如何高效的提取value="*****"中間的*** 望各位不吝賜教
-------------
1) grep -o "value=.*\"" data7 | awk -F'"' '{print $2}'
2) sed 's/.*value="\(.*\)".*/\1/' file
*)
---
兩個文件
a
b
#cat a
a1 b=1 num=3 c=2
a3 b=1 num=3 c=3
bc f=3 num =2 f=3
fa f=4 num=2 f=6
#cat b
a4 b=1 num=6 c=3
a1 b=1 num=5 c=2
bc f=3 num =1 f=3
fb f=4 num=3 f=6
要求對比兩個文件
條件1:如果文件a中有和文件b第1,2,4部分都相同的行則用文件b中該行的第三部分num=x
其x的值減去文件a中該行第三部分num=x其x的值,並將結果連同該行的其他部分寫入文件c
例如:
文件b中第二行a1 b=1 num=5 c=2的第一部分:a1
,第二部分b=1,第4部分c=2和文件a的第一行a1 b=1 num=3
c=2相應部分相同則將結果
a1 b=1 num=2 c=2 寫入文件c
(num=2是文件b的num=5減去文件a的num=3的得來的)
條件2:如果條件1中num后數值相減后該結果為負值則將文件b中的該行直接寫入文件c
例如:b中的第三行bc f=3 num =1 f=3與文件a中的第三行bc f=3 num =2
f=3的1,2,4部分相同,但是num后數值的運算結果為-1
(1減2得來的)所以直接將文件b中的該行bc f=3 num =1 f=3直接計入文件c
條件3:如果文件a中沒有找到和文件b中1,2,4部分相同的行則將文件b中的該行直接寫入文件c
例如:文件b的第四行fb f=4 num=3
f=6,在文件a中無法找到和他第1,2,4部分相同的行所以直接將該行寫入文件寫入文件c
條件4:a或者b本文本身中不會出現第1,2,4部分相同的行
---
test.awk
#!/bin/awk -f
NR==FNR {
sub(/.*=/ ,"" ,$3)
h[$1$2$4] = $3
}
NR>FNR {
i = 0
sub(/.*=/, "" ,$3)
if($1$2$4 in h) {
i = $3 - h[$1$2$4]
}
if(i>0) $3 = "num="i
else $3 = "num="$3
print
}
awk -f test.awk a b > c
*)awk對文件進行分流
$cat file:
00:49:42.025791 14058101005 2008-05-31 09:41:2
-00:00:34.974209 14058101003 2008-05-31 10:31:4
...
目的是把以00開頭的行輸出到一個文件,-00開頭的行輸出到一個文件,用一條awk語句可以實現么?
*)
如何在文件中使用awk設定的變量
參考: #awk -v min=43922 -v max=52059 '{a[$1]}END{for(i=min;i<=max;i++)if(!(i in a))print i}'
*)
3 0.022913642968727541
2 0.022706007307485104
2 0.50444767354650166
3 0.022128299612739447
6 0.025468440060252208
1 0.022856042968727539
。。。
第一列相同則第二列對應值求和。。。輸出$1,sum
這樣的是錯誤的!!!
#awk 'a[$1]+=$2; END{for(i in a) print i,a[i]}' cata3
right :
awk '{a[$1]+=$2} END{for(i in a) print i,a[i]}' cata3
*)
有一個類似於這樣的文本:
16 001agdcdafasd
16 002agdcxxxxxx
23 001adfadfahoh
23 001fsdadggggg
我想要得到
16 001
16 002
23 001
23 002
在awk中,就是取$2的前三個字符,但是不知道如何處理
大家幫幫忙哦,先謝謝了:)
----
1)awk '{print $1,substr($2,1,3)}'
2)sed 's/\(.* ...\).*/\1/' file
3)grep -o '^.\+ \+...' file
*)把文件 file
CHN0401
部門1組
分部門查詢
吳斌
CHN0402
部門2組
查詢
李演
CHN0403
部門3組
查詢
李路
變為
-------------------------------------------
CHN0401 部門1組 分部門查詢 吳斌
CHN0402 部門2組 查詢 李演
CHN0403 部門3組 查詢 李路
1)
awk '/CHN/{h=$1; sub("\n","",h); printf "%s ",h; for(i=0; i<=3; i++) {if(getline var) { sub("\n","",var);} var=sprintf("%s ", var); printf "%s",var; }print "";}' file
2)
$cat ff.awk
#!/bin/awk -f
#
/CHN/{
h=$1;
sub("\n","",h);
printf "%s ",h;
for(i=0; i<=3; i++)
{
if(getline var)
{
sub("\n","",var);
}
var=sprintf("%s ", var);
printf "%s",var;
}
print "";
} file
$ff.awk filename
或
#!/bin/awk -f
#
/CHN/{
s=$0;
for(i=0; i<=3; i++)
{
getline
s=sprintf("%s %s", s,$0);
}
printf "%s", s;
print "";
} file
*替換特定行之間的行
*) 替換注釋行<!-- -->
<!-- <mapping
resource="0.xml" />-->
<mapping resource="1.xml" />
<mapping resource="2.xml" />
<!-- <mapping
resource="3.xml" />
-->
<mapping resource="4.xml" />
<!--
<mapping
resource="5.xml" />
-->
<!-- <mapping resource="6.xml" />-->
<mapping resource="7.xml" />
1)awk 'BEGIN{RS="<!--|-->"}NR%2' urfile
*)使用多個單詞作為分隔符
awk -F'word1|word2' '{print $3}'
*) 把不同的結果定向到不同的文件中去
有這樣個文件
123|0|444
123|1.00|444
588|222|333
現在想把第2個字段為0的取出來輸出到一個文件,並刪除該記錄,用awk如何實現,謝謝
代碼如下:
-----------------------------------------------
[zhengxh@hoverzg stdshell]$ cat dd
123|0|444
123|1.00|444
588|222|333
#注意在輸出的文件名前面要加雙引號
[zhengxh@hoverzg stdshell]$ awk -F'|' '{if($2==0)print >"file1"; else print >"file2"}' dd
[zhengxh@hoverzg stdshell]$ cat file1
123|0|444
[zhengxh@hoverzg stdshell]$ cat file2
123|1.00|444
588|222|333
-----------------------------------------------
*)
比如解析下面一行:
123||name||address||age
我想以“||”為分割符,這樣各個域為“123”, “name”,“age”
1)awk -F"[|]+" '{print $1}' filename
*)單引號的輸出
1) awk 'BEGIN{print "'\'看我的\''";}'
*)找出不含指定字符串的行
awk '!(/abc/||/def/)
找出不含abc或者不含def的列作為條件
-----------------------------------------------
[zhengxh@hoverzg stdshell]$ awk '!(/dd/||/1/) {print }' dd
588||222||333
[zhengxh@hoverzg stdshell]$ cat dd
123||0||444
123||1.00||444
588||222||333
-----------------------------------------------
*)只處理最后一行
1)awk 'END{ print $0}' test
2)tail -1 | awk ...
*)只是處理第一行
1) awk '{print $0; exit}' filename
2) head -1 file | awk ...
*)處理文件中指定的n行
1) awk '{if(NR==n) print }'
2) head -n | tail -m | awk ...
*) 某個文本文件,當逐行讀取時,當發現第一個字段是空格或空值時(cut -d' '
-f1),就將所在行與上行合並。
1)awk '/^[^ \t]/{printf "\n"$0}; /^[ \t]/{printf $0}END{printf "\n"}' file
1*) awk 'BEGIN{getline;printf $0}/^[^ \t]/{printf "\n"$0};\
/^[ \t]/{printf $0}END{printf "\n"}' urfile
#注意如果用print是不能實現的,因為print 會打印一個\n
解釋:
如果前面的字符不是空格就打印一個\n,再打印這一行,
如果是就直接打印但不換行
2)sed ':a;N;/\n[[:blank:]]\+/{s/\n//;ba};P;D' 數據文件
解釋:
:a 設置跳轉標簽
N 讀入下一行
/\n[[:blank:]]\+/{s/\n//;ba}
如果下一行是以空白開頭的話,就把換行符刪除,
然后再讀取下一行,直到讀取到不是以空白開頭的行
P; 打印第一個換行符之前的內容
D; 刪除第一個換行符之前的內容,並重新開始循環
*)
有個文件格式如下:
aaa
bbb
ccc
yyyuu
jjjkkk
sss
aaa
ccc
。。。。
有重復的字符串,要求對每個不一樣的字符串計數並按計數的降序排列輸出。輸出的文件就只有各個不一樣的字符串而已。
sort b | uniq -c | sort
*)
$ cat file
DAA=
123413
ZZASDF
DAA=
123413
ZZASDF
DAA=
123413
ZZASDF
$ awk 'BEGIN{RS="DAA="} {gsub(/[^\n]/,"9",$0); if(length($0)>0) printf "%s %s",RS,$0}' file
*)
-----------------------
各位大牛好:
小的有這樣兩個文件,記錄不同查詢出來的次數。
文件一 a.txt,有兩個字段,一個是次數,一個是pid,具體如下:
2 CC214798313J90000000000
1 CC214798119J90000006000
1 CC214790518J90000001000
1 CC214790518
1 CC214788013J90000005000
1 CC214788013
1 CC214783814J90000003000
1 CC214783814J90000002000
1 CC214783814
1 CC214778610
文件二,b.txt ,也有兩個字段,一個是次數,一個是pid,具體如下:
1 CC153301918J90000010000_765
1 CC120143642J90000043000_765
1 CC000024062J90033095000_765
1 CC000001583J90000044000_765
1 CC000001583J90000046000_768
1 CC130012773J90000076000_765
1 CC130012773J90000063000_765
1 CC130012773J90000064000_765
1 CC130012773J90000051000_765
1 CC130012773J90000052000_765
1 CC138037658J90000044000_538
這兩個文件記錄的pid是可能相同的,我想把這兩個文件組成一個文件:
次數1 次數2 pid
2 0 CC214798313J90000000000
1 0 CC214798119J90000006000
也就是合並兩個文件中的兩個字段 ,組成三個字段的第三個文件。
請假兄弟姐妹們。謝謝
--
*在指定行插入一行
awk '1;NR==1{print "addadf"}' file
-----------------------------------------
*awk能實現對一個文件進行不同條件的匹配,然后按匹配的不同輸出不同的文件嗎??
比如這樣的文件:
##a1a1a1a1
b1:
@c1c1c1c1c1
d1:
%e1e1e1e1
##a2a2a2
b2:
@c2c2c2c2
d2:
%e2e2e2e2
將滿足#開頭的記錄輸出的a文件,將@開頭的記錄輸出的b文件,將%的文件輸出到c文件
所有操作希望通過一個腳本文件實現
這樣條件我都知道怎么去配置就是不知道怎么按條件的不同輸出啊,awk腳本能實現,如果不能怎么去實現它呢。
希望大俠們指教呢
do:
awk 'BEGIN{FS="";a["#"]="a";a["@"]="b";a["%"]="c"}($1 in a){print > a[$1]".txt"}' urfile
awk 'BEGIN{FS="";a["#"]="a";a["@"]="b";a["%"]="c"}($1 in a){print > a[$1]".txt"}' urfile
awk的基本功能是對文件進行指定規則瀏覽和抽取信息。
基本格式:
(1) awk [-F 分隔域] 'command' input-file(s)
(2) 寫入shell腳本中
(3) awk -f awk-script-file input-file(s)
注意:這里如果使用if等編程語句,要用{}括起來。
test
name grade score id
hover 2 96 2003073
twq 3 91 2003074
zsm 4 92 2003075
hzm 5 95 2003076
bl 6 96 2003077
1,文本過濾處理:
(1) awk '{print $0}' test #打印文件的全部內容
注意:這里awk使用函數print用來打印整個文件的內容。其中的$0就表示整個文件的內容。
(2) awk '{print $1}' test #抽取文件test中的第一列
注意:如果awk沒有使用-F指定分隔符號,默認的分隔符號是空格和TAB鍵。
#列出所有的用戶名和登陸的shell名
awk -F : '{print $1,$6}' /etc/passwd
(3) awk -F : '$1=="root" {print $0}' /etc/passwd
指打印用戶名為root的那一行
2,文本格式定制
(1)給輸出信息加上表頭
awk -F : 'BEGIN {print "name shell\n--------------------------------"}
{print $!"\t"$6}' /etc/passwd
(2)
awk -F : 'BEGIN {print "name shell\n--------------------------------"}
{print $!"\t"$6} END {"end-of-report"}' /etc/passwd
3,在awk中使用正則表達式
^ 表示匹配行首的字符
[...] 匹配[]正的任意一個字符
(str1|str2) 匹配含有str1或str2的行
. 匹配任意一個字符
(1)匹配
為使一域匹配一正則表達式,可以使用以下兩種方法:
1)$n~正則表達式
2)if($n~正則表示式) print $0
awk -F: '$0 ~ /^root/' /etc/passwd #打印以root開頭的行
awk -F: '{if($0 ~ /^root/) print $0}' /etc/passwd #和上一句等效
*精確匹配*
#打印名字為root的用戶在/etc/passwd文件中的記錄
awk -F : '$1=="root" {print $0}' /etc/passwd
#打印路徑為/root的用戶在/etc/passwd中的記錄
awk -F : '$6=="\/root" {print $0}' /etc/passwd
4,在awk中使用條件操作符
< 小於 >= 大於等於
<= 小於等於 ~ 匹配正則表達式
== 等於 !~ 不匹配正則表達式
!= 不等於
(1)模糊匹配
i)使用if {if($1~/zhengxh/) print $0}
ii)不用if '$0 ~ /zhengxh/'
ex

awk '$0~/zhengxh/' filename
或awk '{if($0~/zhengxh/) print $0} filename #輸出含有zhengxh的行
或awk '/zhengxh/' filename
(2)精確匹配
$n=="chars"
awk '$1=="zhengxh" {print $0}' filename #輸出第一列等於zhengxh的行
(3)反向匹配
$n !~ /adf/
awk '$1 !~ /zhengxh/ {print $0}' filename #輸出第一列不是zhengxh的行
(4)大小寫匹配
awk '/[zZ]hengxh/' filename #匹配含有zhengxh 或是Zhengxh的字符串
(5)使用或運算
awk '$0 ~ /(zhengxh|hover)/' filename #查找含有zhengxh或hover字串的行
或awk '{if($0~/zhengxh/ OR $0~/hover/) print $0}' filename
(6)內置變量
ARGC 命令行參數個數
ARGV 命令行參數排列
ENVIRON 環境變量支持隊列的
FNR 瀏覽文件的記錄數
FS 設置輸入域分隔符,與-F同
NF 記錄域的個數
NR 已讀的記錄數
OFS 輸出域分隔符
ORS 輸出記錄分隔符
RS 控制記錄分隔符
awk 的具體運用(FAQ)
* 把一個文件中滿足條件的放到一個文件不滿足條件的放到另一個文件
awk -F: '{if(NF==6) print $0 > "yes" else print $0 > "no" }' filename
*如何在awk中使用變量
要注意的是在awk中的表達式一般是用''號括起來的,在shell中單引號是全屏蔽符,所以用單引號使得變量無法生效,在使用shell變量時,可以這樣使用
##########################
#/bin/sh
#
name="zhengxh"
count=`awk -F: '
/'${name}'/{ #這里需要使用變量的地方把變量隔開
sum+=$3
}
END { print sum }
'`
*使用awk輸出文件的倒數第N行
tail -n $N $filename | awk '{if(NR==1) print $0}'
*)如何在AWK中使用外部變量
1)aa="aaaaaaa"
awk '{print "'"${aa}"'"}' $filename
2)
以下使用外部變量時有錯:
#!/bin/bash
filepath=/etc/passwd
user=root
result=`awk -F":" '/$user/ { print $1}' $filepath`
echo $result
$
改正:
awk -F':' '/'"$user"'/{print $1}' $filepath
*如何把AWK中的值,傳送到外部的SHELL變量
使用$() 或 ``
aa=`awk -F: '{print $0}' $filename`
*進行統計
文件aa.txt
一個用戶可能有多個記錄,這時只統計一次:
數據 用戶ID 下載文件名稱 用戶所在地 等。。。。。
20071128,0001,1,null,600571021800,028
20071128,0002,1,null,600571001800,021
20071128,0002,1,null,600571001802,021
20071128,0003,1,null,600571031800,020
20071128,0004,1,null,600571001800,010
統計各個的號碼(最后一個字段)數量
awk -F, '{if(!b[$2$6]){a[$6]++;b[$2$6]++}}END{for(i in a){print i,a[i]}}'
*如何把多個語句放在一句話(一行)中處理
cat "$file" | awk '{ip=$1; i=index($0,"\google"); if(i>1){ua = substr($0,i); print ip "\t" ua}}'
*把記錄
aa,bb,cc [name, address, age]
變成記錄
ip,aa,bb,cc [ip,name,address,age]
awk -F, '{pirntf "\"192.168.5.154\","$0}'
*取一個字符串的首字母
str=abc
echo ${str:0:1}
echo $str|awk '{print substr($0,1,1)}'
echo $str|sed 's/\(.\).*/\1/'
*如何在一字符串的前面加上字符串 addtext
awk '{print "addtext \""$0"\""}' temp
*計算不重復的列的總和
aa|001|23
ac|001|23
bb|002|213
cc|004|32
dd|005|34
awk -F'|' '!a[$1]++{sum+=$3} END{print sum} ' filename
*定義多個分界符
aa cc dd
bb,ee ff
awk -F'[ ,]' '{print $3}' filename
有時候有可能出現多個分隔符號,但是我們需要把它當成一個,這時就要用:
***
#echo "adf::adf:f" | awk -F'[:]+' '{print $2}'
#adf
***
#echo "adf::adf:f" | awk -F':' '{print $2}'
# #輸出空
***
*如何用awk處理這樣的文件格式?
源文件格式:
表1313
客戶經理業績情況表(月報表)
支局所名稱:XXXX儲蓄所 月份:10
客戶經理
業績(累計日積數)
酬金
姓名 代號 活期 整整3月
整整6月 整整1年 整整2年 整整3年
整整5年 整整8年 零整1年 零整3年
零整5年 定活兩便
蘭 37040576 0.00 0.00 0.00
0.00 0.00 0.00 0.00
0.00 0.00 0.00 21340.00
0.00 0.00
禚樹征 37040585 27277.21 120.00 0.00
2965.22 0.00 0.00 0.00
0.00 0.00 0.00 0.00
0.00 845615151469035520.00
秦 37040502 20094.30 0.00 0.00
0.00 0.00 0.00 0.00
0.00 0.00 0.00 0.00
0.00 622937933443235840.00
合 計 444868.41 0.00 0.00
2965.22 0.00 0.00 10764.20
0.00 0.00 0.00 0.00
18600.00 13791245122257916000.00
如何用awk處理成以下格式(只要里面的記錄並用逗號分割每個字段,最后一個字段不要,表頭和表尾不要):
"蘭",37040576,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,21340.00,0.00
"禚樹征",37040585,27277.21,120.00,0.00,2965.22,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
"秦",37040502,20094.30,0.00,0.00,0.00,0.00,0.00,,0.00,0.00,0.00,0.00,0.00,0.00
awk '{sub("[ \t]", ","); print $0}' temp
awk '{sub("[ ,\t]", ","); print $0}' temp
*如何用TAB做分隔符號
awk -F'\t'
awk -F'[ \t]' #默認是這樣,以空格或TAB做分隔符
一般模式:awk -F'rexp' '{}' filename
這里rexp是一個正則表達式,用來指示要使用的分隔符。
*--------------------------
在awk腳本中有下面一段
BEGIN{split("123#456#789",team,"#")}
END{for(i in team) print team}
預測的輸出應該是
123
456
789
啊!
為什么實際的輸出是
456
789
123
呢?
答:
---
while(++i in team) print team[i]
----------------------------
*-awk中使用system()
answer:
ls | awk '{if (system("ls " $0) == 0) {print "file " $0 " exists !"}}'
*-調用外部命令和awk結合
使用getline得到外部命令的輸入f
ls | awk '{getline ll; print $ll}'
--------------------------
*-只輸出第一行的內容
awk '{print; exit}'
*-多shell命令
awk ’BEGIN{while("dir|sed 1,3!d"|getline)print $1}‘
*-在awk的輸出中加單引號
#cat file
rwxrwsrwx gprs 512 GPRS
awk '{printf("%s %s '"'%s'"' %s\n",$1,$2,$3,$4)}' file
在這里要理解的是:上面的表達式分成了三塊,前面的''內的內容是一塊,中間的雙引號內的內容是一塊,最后的單引號里的內容是一塊;由於單引號在雙引號中的作用被屏蔽,所以輸出的變量會帶上單引號。從而達到預定結果。
*-得到df -h 顯示出來的百分數字(去掉百分號)
(1)df -h | awk '{if(NR!=1) print $5}' | cut -d% -f 1
(2)df -h | awk -F'[ \t%]+' '{if(NR!=1) print $5}'
***
實現加和
中間結果如下所示:
CPU usr sys idl
0 13 4 76
1 9 4 79
要想顯示下列結果:
1 22 8 155
***
cat data | awk '{if(NR!=1) a+=$1;b+=$2;c+=$3} END{print a,b,c,d,e}'
***
如何實現以幾個字母中任意一個打頭的字符串的查找
cat data
Mike Harrington:(510) 548-1278:250:100:175
Christian Dobbins:(408) 538-2358:155:90:201
Susan Dalsass:(206) 654-6279:250:60:50
Archie McNichol:(206) 548-1348:250:100:175
Jody Savage:(206) 548-1278:15:188:150
Guy Quigley:(916) 343-6410:250:100:175
Dan Savage:(406) 298-7744:450:300:275
Nancy McNeil:(206) 548-1278:250:80:75
John Goldenrod:(916) 348-4278:250:100:175
Chet Main:(510) 548-5258:50:95:135
Tom Savage:(408) 926-3456:250:168:200
Elizabeth Stachelin:(916) 440-1763:175:75:300
awk -F'[ :]' '$1~/^[MJ] {print $1}'
輸出以D開頭的域
awk -F':' '{for(i=1;i<=NF;i++) if($i~/^D/) print $i}' data2
****每一行的和
統計
#cat ab
a 1
a 2
b 2
awk '{a[$1]+=$2} END{for(i in a) print i,a[i]}' file
-----------------------------------
*對兩個文件的處理
----------
大家好,想請教一個問題,我現在有兩個文件,如下所示,這兩個文件格式都是一樣的。我想首先把文件2的第五列刪除,然后用文件2的第一列減去文件一的第一列,把所得的結果對應的貼到原來第五列的位置,請問這個腳本該怎么編寫?
file1:
50.481 64.634 40.573 1.00 0.00
51.877 65.004 40.226 1.00 0.00
52.258 64.681 39.113 1.00 0.00
52.418 65.846 40.925 1.00 0.00
49.515 65.641 40.554 1.00 0.00
49.802 66.666 40.358 1.00 0.00
48.176 65.344 40.766 1.00 0.00
47.428 66.127 40.732 1.00 0.00
51.087 62.165 40.940 1.00 0.00
52.289 62.334 40.897 1.00 0.00
file2:
48.420 62.001 41.252 1.00 0.00
45.555 61.598 41.361 1.00 0.00
45.815 61.402 40.325 1.00 0.00
44.873 60.641 42.111 1.00 0.00
44.617 59.688 41.648 1.00 0.00
44.500 60.911 43.433 1.00 0.00
43.691 59.887 44.228 1.00 0.00
43.980 58.629 43.859 1.00 0.00
42.372 60.069 44.032 1.00 0.00
43.914 59.977 45.551 1.00 0.00
--答--
awk 'NR==FNR{a[NR]=$1}NR!=FNR{$5=a[FNR]-$1;print}' file2 file1
說明:
當NR==FNR時,是第一個文件,到了第二個文件時FNR會從0開始計數,而NR卻繼續在原來的基礎上自增。
先把第一個文件中要使用的內容保存到一個數組中,然后在處理第二個文件時才使用。
這里包含了很好的處理多個文件的方法,值得借鑒。
-------------------------------------------------
**
源文件如下:
37123456,123456789,601234020200051640,"孔霞","03",123456789,"2008/01/06",1,4000,5060.41
37123456,123456789,601234020200062521,"栗汝禮","03",123456010,"2008/01/06",1,100,110.91
37123456,123456789,601234020200069800,"柯純龍","03",370786017,"2008/01/06",1,20000,19500
37123456,123456789,601234020200069800,"柯純龍","03",123456030,"2008/01/06",1,31000,500
37123456,123456789,601234020200068018,"嚴鳳書","03",123456789,"2008/01/06",2,50000,100163.39
37123456,123456789,601234020200070039,"劉慶","03",123456789,"2008/01/06",2,4000,8000
37123456,123456789,601234020200060554,"王蘭英","03",123456789,"2008/01/06",1,1600,91.26
37123456,123456789,601234020200070039,"劉慶","03",123456789,"2008/01/06",2,4000,4000
37123456,123456789,601234020200067710,"羅有艷","03",123456789,"2008/01/06",2,3000,12012.01
37123456,123456789,601234020200064742,"孫祥婷","03",123456789,"2008/01/06",1,50,12.61
37123456,123456789,601234020200069800,"柯純龍","03",123456030,"2008/01/06",1,200,300
37123456,123456789,601234020200060554,"王蘭英","03",123456789,"2008/01/06",1,1000,1091.26
處理要求如下:
如果第三列中的數據是唯一的,就保留這一行,如果有重復的,就保留最后一個記錄行。
--------答---------
awk -F, '{a[$3]=$0}END{for( i in a)print a[i]}' urfile
------------------------------
*如何快速獲取特定字符串的前2(n)行和后2(n)行
$cat file
put 8
put 9
put 10
abc
put 11
put 12
put 13
put 14
abc
put 15
put 16
put 17
put 18
abc
put 19
put 20
put 21
put 22
put 23
abc
put 24
put 25
put 26
put 27
abc
put 28
put 29
put 30
put 31
put 32
abc
put 33
put 34
put 35
put 36
put 37
$ awk '{a[NR]=$0}/abc/{for(i=2;i>=0;i--) print a[NR-i];for(j=1;j<=2;j++){if(!getline) exit;print}print ""}' urfile
小結:
(1)這里使用了數組的功能,數組在作為緩存是普遍用法,要記住。
但這里如果文件超大的話,緩沖區的負擔太大,應換存自己需要的哪些行(這里我只換存了4行)
$ awk '{a[NR%4]=$0}/abc/{for(i=2;i>=0;i--) print a[(NR-i)%4];for(j=1;j<=2;j++){if(!getline) exit;print}print ""}' urfile
(2)使用了getline函數-- $ man awk 就知道,getline函數的作用是: 1)讀取下一行2)set $0
注意這兩個元素的應用.
*)如何提取aaaa12123adsf adfadfbbbb 的aaaa和bbbb中間的內容
$cat file
adfaaaaadfadfadfdfadabbbb
adfaaaaadf ad323452 adfadfdfadabbbbz
$
1)sed -e 's/.*\(aaaa\)\(.*\)\(bbbb\).*/\2/g' file
2)sed -e 's/.*\(a\{3\}\)\(.*\)\(b\{3\}\).*/\2/g' file
3)echo "aaaa121312dfadfbbbbb" | awk -F'aaaa|bbbb' '{print $2}'
*)我以如下字符要處理
a 123
b 124
c 125
a 126
d 127
e 128
ac 129
如果第一列出現兩次或兩次以上將其打印出來,並計算出現次數。
$ awk '{a[$1]++;} END{for(i in a) if(a[i]>=2) {print i,a[i]}}' file
分析: 由以上的命令可以得到流程:
a["a"] 2
a["b"] 1
a["c"] 1
a["d"] 1
a["e"] 1
a["ac"] 1
而for(i in a) 則是要遍歷的i的值是:a,b,c,d,e,ac
*)去掉重復的行
awk '!a[$0]++' file
*)去掉重復行,並保持順序不變
awk 'f[$0]!=1{print;f[$0]=1}'
*)打印重復行
1)awk '{a[$0]++} END{for(i in a) {if(a[i]>1){print i}}}' filename
2)sort cc | uniq -dc
*)如何匹配多個模式
1)awk '/p1|p2/' file
2)awk '/zhengxh|\<root\>' file
*)設定字段分隔符
1)awk -F':' '{OFS="-"}{print $1,$2,$3}' file
*)范圍查找
1)awk -F':' '/20080501[2-9]/' file
*)數字計算求和 file:
hammers QTY: 5 PRICE: 7.99 TOTAL: 39.95
drills QTY: 2 PRICE: 29.99 TOTAL: 59.98
punches QTY: 7 PRICE: 3.59 TOTAL: 25.13
drifts QTY: 2 PRICE: 4.09 TOTAL: 8.18
bits QTY: 55 PRICE: 1.19 TOTAL: 65.45
saws QTY: 123 PRICE: 14.99 TOTAL: 1843.77
nails QTY: 800 PRICE: .19 TOTAL: 152
screws QTY: 80 PRICE: .29 TOTAL: 23.2
brads QTY: 100 PRICE: .24 TOTAL: 24
1)awk '{x=x+$2}' file
*)
---
3 0.022913642968727541
2 0.022706007307485104
2 0.50444767354650166
3 0.022128299612739447
6 0.025468440060252208
1 0.022856042968727539
第一列相同則第二列對應值求和。。。輸出$1,sum
---
1)awk '{a[$1]=+$2; b["2"$1]++} END{for(i in a) if(b["2"i]>1) print i,a[i]}' file
*)我以如下字符要處理
a 123
b 124
c 125
a 126
d 127
e 128
ac 129
如果第一列出現 兩次或兩次以上 將其打印出來,並計算出現次數。
1)awk '{a[$1]++} END{for(i in a) print i,a[i]}' file
------
*)awk中如何顯示大數據
1)awk '{printf"%.f\n", NR + 1211439408282}' filename
*)awk使用外部變量
1)awk '{if($3=="'$a'") print $1,$2,"'$b'",$4}' text
2)awk '{if($3=='\"$a\"') print $1,$2,'\"$b\"',$4}' text
*)
文件內容:
74683 1001
74683 1002
74683 1011
74684 1000
74684 1001
74684 1002
74685 1001
74685 1011
74686 1000
....
100085 1000
100085 1001
文件就兩列,希望處理成
74683 1001 1002 1011
74684 1000 1001 1002
...
就是只要第一列數字相同, 就把他們的第二列放一行上,中間空格分開
--------------
1) awk '{a[$1]=sprintf("%s %s", a[$1],$2)} END{for(i in a) print i,a[i]}' file
2) awk '{a[$1]=a[$1]" "$2} END{for(i in a)print i,a[i]}' data13
*)
76523 1001 1002
76524 1002 1003
76526 1000 1003
76528 1000
....
100025 1000 1025
請教下, 文件第一列已按大小排序, 現在想按第一列的順序, 把沒有出現的行數補上
實現
76523 1001 1002
76524 1002 1003
76525
76526 1000 1003
76527
76528 1000
....
100025 1000 1025
怎樣能夠直接補上這些缺失的行
-------------------
1)???????
*)
每個字段形如 <data name="CYRSBH" value="320400725220211"/>,如何高效的提取value="*****"中間的*** 望各位不吝賜教
-------------
1) grep -o "value=.*\"" data7 | awk -F'"' '{print $2}'
2) sed 's/.*value="\(.*\)".*/\1/' file
*)
---
兩個文件
a
b
#cat a
a1 b=1 num=3 c=2
a3 b=1 num=3 c=3
bc f=3 num =2 f=3
fa f=4 num=2 f=6
#cat b
a4 b=1 num=6 c=3
a1 b=1 num=5 c=2
bc f=3 num =1 f=3
fb f=4 num=3 f=6
要求對比兩個文件
條件1:如果文件a中有和文件b第1,2,4部分都相同的行則用文件b中該行的第三部分num=x
其x的值減去文件a中該行第三部分num=x其x的值,並將結果連同該行的其他部分寫入文件c
例如:
文件b中第二行a1 b=1 num=5 c=2的第一部分:a1
,第二部分b=1,第4部分c=2和文件a的第一行a1 b=1 num=3
c=2相應部分相同則將結果
a1 b=1 num=2 c=2 寫入文件c
(num=2是文件b的num=5減去文件a的num=3的得來的)
條件2:如果條件1中num后數值相減后該結果為負值則將文件b中的該行直接寫入文件c
例如:b中的第三行bc f=3 num =1 f=3與文件a中的第三行bc f=3 num =2
f=3的1,2,4部分相同,但是num后數值的運算結果為-1
(1減2得來的)所以直接將文件b中的該行bc f=3 num =1 f=3直接計入文件c
條件3:如果文件a中沒有找到和文件b中1,2,4部分相同的行則將文件b中的該行直接寫入文件c
例如:文件b的第四行fb f=4 num=3
f=6,在文件a中無法找到和他第1,2,4部分相同的行所以直接將該行寫入文件寫入文件c
條件4:a或者b本文本身中不會出現第1,2,4部分相同的行
---
test.awk
#!/bin/awk -f
NR==FNR {
sub(/.*=/ ,"" ,$3)
h[$1$2$4] = $3
}
NR>FNR {
i = 0
sub(/.*=/, "" ,$3)
if($1$2$4 in h) {
i = $3 - h[$1$2$4]
}
if(i>0) $3 = "num="i
else $3 = "num="$3
}
awk -f test.awk a b > c
*)awk對文件進行分流
$cat file:
00:49:42.025791 14058101005 2008-05-31 09:41:2
-00:00:34.974209 14058101003 2008-05-31 10:31:4
...
目的是把以00開頭的行輸出到一個文件,-00開頭的行輸出到一個文件,用一條awk語句可以實現么?
*)
如何在文件中使用awk設定的變量
參考: #awk -v min=43922 -v max=52059 '{a[$1]}END{for(i=min;i<=max;i++)if(!(i in a))print i}'
*)
3 0.022913642968727541
2 0.022706007307485104
2 0.50444767354650166
3 0.022128299612739447
6 0.025468440060252208
1 0.022856042968727539
。。。
第一列相同則第二列對應值求和。。。輸出$1,sum
這樣的是錯誤的!!!
#awk 'a[$1]+=$2; END{for(i in a) print i,a[i]}' cata3
right :
awk '{a[$1]+=$2} END{for(i in a) print i,a[i]}' cata3
*)
有一個類似於這樣的文本:
16 001agdcdafasd
16 002agdcxxxxxx
23 001adfadfahoh
23 001fsdadggggg
我想要得到
16 001
16 002
23 001
23 002
在awk中,就是取$2的前三個字符,但是不知道如何處理
大家幫幫忙哦,先謝謝了:)
----
1)awk '{print $1,substr($2,1,3)}'
2)sed 's/\(.* ...\).*/\1/' file
3)grep -o '^.\+ \+...' file
*)把文件 file
CHN0401
部門1組
分部門查詢
吳斌
CHN0402
部門2組
查詢
李演
CHN0403
部門3組
查詢
李路
變為
-------------------------------------------
CHN0401 部門1組 分部門查詢 吳斌
CHN0402 部門2組 查詢 李演
CHN0403 部門3組 查詢 李路
1)
awk '/CHN/{h=$1; sub("\n","",h); printf "%s ",h; for(i=0; i<=3; i++) {if(getline var) { sub("\n","",var);} var=sprintf("%s ", var); printf "%s",var; }print "";}' file
2)
$cat ff.awk
#!/bin/awk -f
#
/CHN/{
h=$1;
sub("\n","",h);
printf "%s ",h;
for(i=0; i<=3; i++)
{
if(getline var)
{
sub("\n","",var);
}
var=sprintf("%s ", var);
printf "%s",var;
}
print "";
} file
$ff.awk filename
或
#!/bin/awk -f
#
/CHN/{
s=$0;
for(i=0; i<=3; i++)
{
getline
s=sprintf("%s %s", s,$0);
}
printf "%s", s;
print "";
} file
*替換特定行之間的行
*) 替換注釋行<!-- -->
<!-- <mapping
resource="0.xml" />-->
<mapping resource="1.xml" />
<mapping resource="2.xml" />
<!-- <mapping
resource="3.xml" />
-->
<mapping resource="4.xml" />
<!--
<mapping
resource="5.xml" />
-->
<!-- <mapping resource="6.xml" />-->
<mapping resource="7.xml" />
1)awk 'BEGIN{RS="<!--|-->"}NR%2' urfile
*)使用多個單詞作為分隔符
awk -F'word1|word2' '{print $3}'
*) 把不同的結果定向到不同的文件中去
有這樣個文件
123|0|444
123|1.00|444
588|222|333
現在想把第2個字段為0的取出來輸出到一個文件,並刪除該記錄,用awk如何實現,謝謝
代碼如下:
-----------------------------------------------
[zhengxh@hoverzg stdshell]$ cat dd
123|0|444
123|1.00|444
588|222|333
#注意在輸出的文件名前面要加雙引號
[zhengxh@hoverzg stdshell]$ awk -F'|' '{if($2==0)print >"file1"; else print >"file2"}' dd
[zhengxh@hoverzg stdshell]$ cat file1
123|0|444
[zhengxh@hoverzg stdshell]$ cat file2
123|1.00|444
588|222|333
-----------------------------------------------
*)
比如解析下面一行:
123||name||address||age
我想以“||”為分割符,這樣各個域為“123”, “name”,“age”
1)awk -F"[|]+" '{print $1}' filename
*)單引號的輸出
1) awk 'BEGIN{print "'\'看我的\''";}'
*)找出不含指定字符串的行
awk '!(/abc/||/def/)
找出不含abc或者不含def的列作為條件
-----------------------------------------------
[zhengxh@hoverzg stdshell]$ awk '!(/dd/||/1/) {print }' dd
588||222||333
[zhengxh@hoverzg stdshell]$ cat dd
123||0||444
123||1.00||444
588||222||333
-----------------------------------------------
*)只處理最后一行
1)awk 'END{ print $0}' test
2)tail -1 | awk ...
*)只是處理第一行
1) awk '{print $0; exit}' filename
2) head -1 file | awk ...
*)處理文件中指定的n行
1) awk '{if(NR==n) print }'
2) head -n | tail -m | awk ...
*) 某個文本文件,當逐行讀取時,當發現第一個字段是空格或空值時(cut -d' '
-f1),就將所在行與上行合並。
1)awk '/^[^ \t]/{printf "\n"$0}; /^[ \t]/{printf $0}END{printf "\n"}' file
1*) awk 'BEGIN{getline;printf $0}/^[^ \t]/{printf "\n"$0};\
/^[ \t]/{printf $0}END{printf "\n"}' urfile
#注意如果用print是不能實現的,因為print 會打印一個\n
解釋:
如果前面的字符不是空格就打印一個\n,再打印這一行,
如果是就直接打印但不換行
2)sed ':a;N;/\n[[:blank:]]\+/{s/\n//;ba};P;D' 數據文件
解釋:
:a 設置跳轉標簽
N 讀入下一行
/\n[[:blank:]]\+/{s/\n//;ba}
如果下一行是以空白開頭的話,就把換行符刪除,
然后再讀取下一行,直到讀取到不是以空白開頭的行
P; 打印第一個換行符之前的內容
D; 刪除第一個換行符之前的內容,並重新開始循環
*)
有個文件格式如下:
aaa
bbb
ccc
yyyuu
jjjkkk
sss
aaa
ccc
。。。。
有重復的字符串,要求對每個不一樣的字符串計數並按計數的降序排列輸出。輸出的文件就只有各個不一樣的字符串而已。
sort b | uniq -c | sort
*)
$ cat file
DAA=
123413
ZZASDF
DAA=
123413
ZZASDF
DAA=
123413
ZZASDF
$ awk 'BEGIN{RS="DAA="} {gsub(/[^\n]/,"9",$0); if(length($0)>0) printf "%s %s",RS,$0}' file
*)
-----------------------
各位大牛好:
小的有這樣兩個文件,記錄不同查詢出來的次數。
文件一 a.txt,有兩個字段,一個是次數,一個是pid,具體如下:
2 CC214798313J90000000000
1 CC214798119J90000006000
1 CC214790518J90000001000
1 CC214790518
1 CC214788013J90000005000
1 CC214788013
1 CC214783814J90000003000
1 CC214783814J90000002000
1 CC214783814
1 CC214778610
文件二,b.txt ,也有兩個字段,一個是次數,一個是pid,具體如下:
1 CC153301918J90000010000_765
1 CC120143642J90000043000_765
1 CC000024062J90033095000_765
1 CC000001583J90000044000_765
1 CC000001583J90000046000_768
1 CC130012773J90000076000_765
1 CC130012773J90000063000_765
1 CC130012773J90000064000_765
1 CC130012773J90000051000_765
1 CC130012773J90000052000_765
1 CC138037658J90000044000_538
這兩個文件記錄的pid是可能相同的,我想把這兩個文件組成一個文件:
次數1 次數2 pid
2 0 CC214798313J90000000000
1 0 CC214798119J90000006000
也就是合並兩個文件中的兩個字段 ,組成三個字段的第三個文件。
請假兄弟姐妹們。謝謝
--
*在指定行插入一行
awk '1;NR==1{print "addadf"}' file
-----------------------------------------
*awk能實現對一個文件進行不同條件的匹配,然后按匹配的不同輸出不同的文件嗎??
比如這樣的文件:
##a1a1a1a1
b1:
@c1c1c1c1c1
d1:
%e1e1e1e1
##a2a2a2
b2:
@c2c2c2c2
d2:
%e2e2e2e2
將滿足#開頭的記錄輸出的a文件,將@開頭的記錄輸出的b文件,將%的文件輸出到c文件
所有操作希望通過一個腳本文件實現
這樣條件我都知道怎么去配置就是不知道怎么按條件的不同輸出啊,awk腳本能實現,如果不能怎么去實現它呢。
希望大俠們指教呢
do:
awk 'BEGIN{FS="";a["#"]="a";a["@"]="b";a["%"]="c"}($1 in a){print > a[$1]".txt"}' urfile
awk 'BEGIN{FS="";a["#"]="a";a["@"]="b";a["%"]="c"}($1 in a){print > a[$1]".txt"}' urfile
*)問題
有如下文檔,如何把 1048576 44 作為$3,$4個域輸出,把Driver te作為一個域?
#cat data
Driver te 2E00000 1048576 44 1048532 1048532 1048532
答:這個問題首先要處理的是Driver te,要把它當成一個域,就要把它當中的空格替換掉再處理。方法如下:
awk -F'[ \t]+' 'sub(" ","#"){print $3,$4}' data