linux awk命令例子教程解读
时间:2015-05-02 01:58 来源:linux.it.net.cn 作者:IT
有关awk命令的例子,awk 小例子解读,通过实例学习linux awk命令的用法,awk命令用于格式化输出匹配指定条件的字符串,感兴趣的朋友参考下。
1、awk '/555555*/' test
打印所有包含模式/555555*/的行
2、awk '{print $1}' test
打印文件的第一个字段,字段从行的左端开始,以空白符分隔
3:awk '{print $1,$3}' test
打印文件的第一,第三个字段
4:awk '/555555/{print $1,$3}' test
打印包含模式/555555/的第一,第三个字段
5:
awk '/zhangfei/{print "\t\twu hu shangjiang:" $1,$2 "!"}'
wu hu shangjiang:zhangfei xiuhua!
\t:制表符,tab键
6.打印数字时,可能需要控制数字的格式。这可以通过printf函数来实现,但是,通过设置一个特殊的awk变量OFMT,使用print函数时也可以控制数字的打印格式。OFMT的默认值时“%.6gd",表示只打印小数部分的前六位。
awk 'BEGIN{OFMT="%.2f";print 1.23456789,12E-2}'
1.23 0.12
如果设置了变量OFMT,在打印浮点数时,就只打印小数部分的前两位。百分号表示接下来要定义格式。
BEGIN:必须大写
7:
root@localhost tmp]# awk '{max=($1>$2)?$1:$2;print max}' filename
如果记录的第一个字段的值大于第二个字段的值,则把问号后面那个表达式的值赋给max,否则就将冒号后面的那个表单时的赋给max。
8、
awk -F: 'NF != 7{printf("line %d,does not have 7 fields: %s\n",NR,$0)} $1 !~/[A-Za-z0-9]/{printf("line %d,nonalphanunmeric user id: %s\n",NR,$0)} $2=="*"{printf("line %d,no password:%s\n",NR,$0)}' passwd
awk的字段分隔 符是冒号;如果字段数(NF)不等于7,则执行接下来的操作块;printf函数打印字符串“line<行号>,does not have 7 fields:”,后面跟上当前记录的记录号(NR)和记录本身($0);如果第一个字段($1)中不含任何字母和数字字符,printf函数就打印字符 串“nonalphanumberic user id:”,后面跟上当前记录的记录号和内容;如果第二个字段是一个星号,就打印字符串“no passwd:",后面跟上记录号和记录本身。
9、用awk命令处理文件"grade.txt":
M.Tansley 05/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansley 05/99 4712 Brown-2 12 30 28
#打印整个文件
zhuyupeng@zhuyupeng-PC ~
$ awk '{print $0}' grade.txt
M.Tansley 05/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansley 05/99 4712 Brown-2 12 30 28
#打印第一和第四个域
zhuyupeng@zhuyupeng-PC ~
$ awk '{print $1,$4}' grade.txt
M.Tansley Green
J.Lulu green
P.Bunny Yellow
J.Troll Brown-3
L.Tansley Brown-2
#打印表头
zhuyupeng@zhuyupeng-PC ~
$ awk 'BEGIN {print "Name Belt\n---------------------------"}
> {print $1"\t"$4}' grade.txt
Name Belt
---------------------------
M.Tansley Green
J.Lulu green
P.Bunny Yellow
J.Troll Brown-3
L.Tansley Brown-2
附,awk例子解读
awk ' NR < 11 ' #不规范,不建议,浪费时间
awk读取前11行(不包括第11行)。如前所述,这里省略了动作打印输出print。匹配模式是变量NR需要小于11,NR即为当前的行号。这个写法很简单,但是有一个问题,在NR大于10的时候,awk其实还是对每行进行了判断,如果文件很大,比如说有上万行,浪费的时间是无法忽略的。
因此,更好的写法是:
awk '1; NR = 10 { exit }' #我的理解是从第一行开始读数据,将第10行到数据读完后退出。
第一句对当前行进行输出。第二句判断是不是已经到了第10行,如果是则退出。
输出文件的第一行(模拟 head -n filename 将n用1替代 )
awk 'NR > 1 { exit }; 1'
这个例子与前一个很相似,中心思想就是第二行就退出。
输出文件的最后两行(模拟 tail -n filename其中n取值为2 )
awk '{ y=x "n" $0; x=$0}; END { print y }' #效率太低不推荐
第一句总是把一个在当前行前面再加上变量x的内容赋值给y,然后用x记录当前行内容。这样的效果是y的内容始终是上一行 加上当前行的内容。在最后,输出y的内容。如果仔细看的话,不难发现这个写法是很不高效的,因为它不停的进行赋值和字符串连接,只为了找到最后一行!所 以,如果你想要输出文件的最后两行,tail -n 2是最好的选择。
输出文件的最后一行(模拟 tail -n filename 其中n取值为1 )
awk 'END { print }'
句法方面没什么好说的,print省略参数即是等价于print $0。但是这个语句可能不能被非GNU awk的某些awk版本正常执行,如果为了兼容,下面的写法是最安全的:
awk '{ rec = $0 }; END { print rec }' #这个写法更具有兼容性
输出只匹配某些模式的行(模拟 grep )
awk '/regex/'
输出不匹配某些模式的行(模拟 grep -v )
awk '!/regex/'
匹配模式前加“!”就是否定判断结果。
输出匹配模式的行的上一行,而非当前行
awk '/regex/ { print x }; { x = $0 }'
变量x总是用来记录上一行的内容,如果模式匹配了当前行,则输出x的内容。
输出匹配模式的下一行
awk '/regex/ { getline; print }'
这里使用了getline函数取得下一行的内容并输出。getline的作用是将$0的内容置为下一行的内容,并同时更新NR,NF,FNR变量。如果匹配的是最后一行,getline会出错,$0不会被更新,最后一行会被打印。
输出匹配AA 或 BB 或 CC的行
awk '/AA|BB|CC/'
正则表达式。
输出长过65个字符的行
awk 'length > 64'
length([str])返回字符串的长度,如果参数省略,即是以$0作为参数,括号也可以省略了。
输出短于65个字符的行
awk 'length < 65'
和上例基本一样。
输出从匹配行到最后一样的内容
awk '/regex/,0'
这里使用了“pattern1,pattern2”的形式来指定一个匹配的范围,其中pattern2这里为0,也就是false,所以一直会匹配到文件结束。
从第8行输出到第12行
awk 'NR==8,NR==12'
同上例,这也是个范围匹配。
输出第52行
awk 'NR==52' #不建议因为到了第52行awk还会继续往下读取下列的行。
如果想要少执行些不必要的循环,就这样写:
awk 'NR==52 {print;exit}' #建议用这个写法
输出两次正则表达式匹配之间的行
awk '/regex1/, /regex2/'
删除所有的空行
awk NF # NF为真即是非空行。
另外一种写法是用正则表达式:
awk '/./'
这个很类似grep .的思路,但是是不如awk NF好的,因为“.”也是可以匹配空格和TAB的。
打印出空行行号
awk '/^$/{print NR}' filename
同理:打印出含有字符good的行号
awk '/good/{print NR}' filename
打印报告头和结尾 #没有验证,我也没看懂
awk 'BEGIN {print "numAtnumBn------------"} {print $1"t"$2} END {print "ENDAt ENDBn-----------"}' test.txt
numA numB
------------
1 2
3 4
ENDA ENDB
-----------
=============================
< 小于
<= 小于等于
== 等于
!= 不等于
> 大于
>= 大于等于
~ 匹配正则表达式
!~ 不匹配正则表达式
b 退格键
f 走纸换页
n 新行
r 回车键
t tab键 #特别注意这几个红色字体,常用到
ddd 八进制值
c 任意其他特殊字符
例子------------
源文件:
[root@BJIT tmp]# more test.txt
1 a
3 b
5 c
7 a
9 b
15 c
用if判断匹配
[root@BJIT tmp]# awk '{if($1>5) print $1}' test.txt #将第一列中数值大于5的数值输出
7
9
15
[root@BJIT tmp]# awk '{if($2~/a/) print $1}' test.txt #如果第二列和a匹配,则输出他们对应的第一列到数值
1
7
用==号匹配——== #一个=是赋值的含义,两个==才是相等表条件
[root@BJIT tmp]# awk '$1=="3" {print $0}' test.txt #如果第一列等于3则输出其在$0当前所有行对应的全部
3 b
匹配正则
[root@BJIT tmp]# awk '$1 ~ ".5" {print $1}' test.txt #不是很理解注意5前有个小数点
15
[root@BJIT tmp]# awk '{if($2~/c/)print $1}' test.txt #如果第2列有匹配的c则输出其对应在第一列的数值
5
15
关系匹配:
[root@BJIT tmp]# awk '$1 ~ "5|7" {print $0}' test.txt #第一列中只要有5或者7匹配则输出其对应的全部
5 c
7 a
15 c
AND匹配——&&:
[root@BJIT tmp]# awk '$1=="5" && $2=="c" {print $0}' test.txt #如果第一列有5且其在第二列中对应c则输出
5 c
或匹配——||:两边任意为真 # 或不是一条竖线也可以吗,疑问?
[root@BJIT tmp]# awk '$2=="a" || $1=="15" {print $0}' test.txt
1 a
7 a
15 c
判断不匹配——! # 感叹号在正则表达式中表示的是非,即否定的含义。
[root@BJIT tmp]# awk '$1!="3" {print $0}' test.txt
1 a
5 c
7 a
9 b
15 c
[root@BJIT tmp]# awk '{if($2!~/a/) print $0}' test.txt
3 b
5 c
9 b
15 c
NR 和 NF
NR:记录已读的记录数
NF:浏览记录的域个数
[root@BJIT tmp]# awk '{print NR"\t"NF"\t"$0}' test.txt # 注意这里到转义字符t表示tab占位符。
1 2 1 a
2 2 3 b
3 2 5 c
4 2 7 a
5 2 9 b
6 2 15 c
[root@BJIT tmp]# awk '{if(NR>0 && $1>7) print $0}' test.txt
9 b
15 c
[root@BJIT tmp]# awk '{if ($1==15)print $NF}' test.txt $NF打印最后域
c # $NF表示的是变量NF的域,即她所对应的$0中最后一个数值。
域值比较(两种方法)
[root@BJIT tmp]# awk '{if($1<$2)print $0}' test.txt1 # 没有看懂
1 a
3 b
5 c
7 a
9 b
15 c
[root@BJIT tmp]# awk 'BEGIN {num=15}{if($1==num)print $0}' test.txt
15 c #从数字15开始,如果第一列中变量的取值有等于15的就全部输出
修改数值域取值:
[root@BJIT tmp]# awk '{$1=$1-2;print $1}' test.txt # 将第一列减去2之后在赋值给原来的数值
-1
1
3
5
7
13
[root@BJIT tmp]# awk '{if($1>2)($1="test"); print $0}' test.txt
# 全部输出且如果第一列中有数值大于2,则用test替代。
1 a
test b
test c
test a
test b
test c
[root@BJIT tmp]# awk '{if($1==5){$1="test";print $1}}' test.txt
test
数值相加:
[root@BJIT tmp]# awk '{tot+=$1}; {print $1,$2} END{print tot}' test.txt
# +=是一个正则表达式,再次即tot等于$1列中所有数字之和,因为$1表示的是列,而awk在执行的时候是逐行扫描读取的。 最后END输出这个tot的最终数值。
1 a
3 b
5 c
7 a
9 b
15 c
40
[root@BJIT tmp]# awk '{tot+=$1}; {print $1,$2} END{print tot/100}' test.txt
# 将相加的结果除以100
1 a
3 b
5 c
7 a
9 b
15 c
0.4
替换字符串: (试验中替换成字母不成功)
[root@BJIT tmp]# awk 'gsub(/3/,123) {print $0}' test.txt
123 b
按照起始位置及长度返回字符串
[root@BJIT tmp]# more test2.txt
12345678
1234567
123456
12345
[root@BJIT tmp]# awk '{print substr($1,1,3)}' test2.txt
123
123
123
123
[root@BJIT tmp]# awk '$1==12345678 {print substr($1,1,5)}' test2.txt
12345
[root@BJIT tmp]# awk '$1==12345678 {print substr($1,3,5)}' test2.txt
34567
[root@BJIT tmp]# echo 12345678 | awk '{print substr ($1,3,6)}'
345678
字符
[root@BJIT tmp]# awk 'BEGIN {print "AtBnCtD"}'
A B
C D
删掉每行的最后一个字符
awk -F'|' '{print $1"|"$2"|"$3"|"$4}' filename
sed 's/.$//g' filename
源文件:
cat filename
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
将其中的空格都以tab键替换
awk '{print $1"t"$2"t"$3"t"$4}' filename
awk 'BEGIN {OFS="t"}{print $1,$2,$3,$4}' filename
(责任编辑:IT)
有关awk命令的例子,awk 小例子解读,通过实例学习linux awk命令的用法,awk命令用于格式化输出匹配指定条件的字符串,感兴趣的朋友参考下。
1、awk '/555555*/' test
2、awk '{print $1}' test
3:awk '{print $1,$3}' test
4:awk '/555555/{print $1,$3}' test 5:
awk '/zhangfei/{print "\t\twu hu shangjiang:" $1,$2 "!"}'
wu hu shangjiang:zhangfei xiuhua! \t:制表符,tab键
6.打印数字时,可能需要控制数字的格式。这可以通过printf函数来实现,但是,通过设置一个特殊的awk变量OFMT,使用print函数时也可以控制数字的打印格式。OFMT的默认值时“%.6gd",表示只打印小数部分的前六位。
awk 'BEGIN{OFMT="%.2f";print 1.23456789,12E-2}'
1.23 0.12
如果设置了变量OFMT,在打印浮点数时,就只打印小数部分的前两位。百分号表示接下来要定义格式。 7:
root@localhost tmp]# awk '{max=($1>$2)?$1:$2;print max}' filename
如果记录的第一个字段的值大于第二个字段的值,则把问号后面那个表达式的值赋给max,否则就将冒号后面的那个表单时的赋给max。 8、
awk -F: 'NF != 7{printf("line %d,does not have 7 fields: %s\n",NR,$0)} $1 !~/[A-Za-z0-9]/{printf("line %d,nonalphanunmeric user id: %s\n",NR,$0)} $2=="*"{printf("line %d,no password:%s\n",NR,$0)}' passwd
awk的字段分隔 符是冒号;如果字段数(NF)不等于7,则执行接下来的操作块;printf函数打印字符串“line<行号>,does not have 7 fields:”,后面跟上当前记录的记录号(NR)和记录本身($0);如果第一个字段($1)中不含任何字母和数字字符,printf函数就打印字符 串“nonalphanumberic user id:”,后面跟上当前记录的记录号和内容;如果第二个字段是一个星号,就打印字符串“no passwd:",后面跟上记录号和记录本身。
9、用awk命令处理文件"grade.txt":
M.Tansley 05/99 48311 Green 8 40 44
#打印第一和第四个域
#打印表头 附,awk例子解读 awk ' NR < 11 ' #不规范,不建议,浪费时间 awk读取前11行(不包括第11行)。如前所述,这里省略了动作打印输出print。匹配模式是变量NR需要小于11,NR即为当前的行号。这个写法很简单,但是有一个问题,在NR大于10的时候,awk其实还是对每行进行了判断,如果文件很大,比如说有上万行,浪费的时间是无法忽略的。
因此,更好的写法是:
输出文件的第一行(模拟 head -n filename 将n用1替代 )
输出文件的最后两行(模拟 tail -n filename其中n取值为2 )
输出文件的最后一行(模拟 tail -n filename 其中n取值为1 )
输出只匹配某些模式的行(模拟 grep )
输出不匹配某些模式的行(模拟 grep -v )
输出匹配模式的行的上一行,而非当前行
输出匹配AA 或 BB 或 CC的行
输出长过65个字符的行
输出从匹配行到最后一样的内容
从第8行输出到第12行
输出第52行
输出两次正则表达式匹配之间的行
删除所有的空行
打印出空行行号
打印报告头和结尾 #没有验证,我也没看懂
numA numB
ENDA ENDB
=============================
b 退格键
例子------------
[root@BJIT tmp]# more test.txt
1 a 3 b 5 c 7 a 9 b 15 c
用if判断匹配
[root@BJIT tmp]# awk '{if($1>5) print $1}' test.txt #将第一列中数值大于5的数值输出
7 9 15 [root@BJIT tmp]# awk '{if($2~/a/) print $1}' test.txt #如果第二列和a匹配,则输出他们对应的第一列到数值 1 7
用==号匹配——== #一个=是赋值的含义,两个==才是相等表条件
[root@BJIT tmp]# awk '$1=="3" {print $0}' test.txt #如果第一列等于3则输出其在$0当前所有行对应的全部
3 b
匹配正则
[root@BJIT tmp]# awk '$1 ~ ".5" {print $1}' test.txt #不是很理解注意5前有个小数点
15 [root@BJIT tmp]# awk '{if($2~/c/)print $1}' test.txt #如果第2列有匹配的c则输出其对应在第一列的数值 5 15
关系匹配:
[root@BJIT tmp]# awk '$1 ~ "5|7" {print $0}' test.txt #第一列中只要有5或者7匹配则输出其对应的全部
5 c 7 a 15 c
AND匹配——&&:
[root@BJIT tmp]# awk '$1=="5" && $2=="c" {print $0}' test.txt #如果第一列有5且其在第二列中对应c则输出
5 c
或匹配——||:两边任意为真 # 或不是一条竖线也可以吗,疑问?
[root@BJIT tmp]# awk '$2=="a" || $1=="15" {print $0}' test.txt
1 a 7 a 15 c
判断不匹配——! # 感叹号在正则表达式中表示的是非,即否定的含义。
[root@BJIT tmp]# awk '$1!="3" {print $0}' test.txt
1 a 5 c 7 a 9 b 15 c [root@BJIT tmp]# awk '{if($2!~/a/) print $0}' test.txt 3 b 5 c 9 b 15 c
NR 和 NF
[root@BJIT tmp]# awk '{print NR"\t"NF"\t"$0}' test.txt # 注意这里到转义字符t表示tab占位符。
[root@BJIT tmp]# awk '{if(NR>0 && $1>7) print $0}' test.txt
[root@BJIT tmp]# awk '{if ($1==15)print $NF}' test.txt $NF打印最后域
域值比较(两种方法)
[root@BJIT tmp]# awk '{if($1<$2)print $0}' test.txt1 # 没有看懂
1 a 3 b 5 c 7 a 9 b 15 c [root@BJIT tmp]# awk 'BEGIN {num=15}{if($1==num)print $0}' test.txt 15 c #从数字15开始,如果第一列中变量的取值有等于15的就全部输出
修改数值域取值:
[root@BJIT tmp]# awk '{$1=$1-2;print $1}' test.txt # 将第一列减去2之后在赋值给原来的数值
[root@BJIT tmp]# awk '{if($1>2)($1="test"); print $0}' test.txt
[root@BJIT tmp]# awk '{if($1==5){$1="test";print $1}}' test.txt
数值相加:
[root@BJIT tmp]# awk '{tot+=$1}; {print $1,$2} END{print tot}' test.txt
[root@BJIT tmp]# awk '{tot+=$1}; {print $1,$2} END{print tot/100}' test.txt
替换字符串: (试验中替换成字母不成功)
[root@BJIT tmp]# awk 'gsub(/3/,123) {print $0}' test.txt
123 b
按照起始位置及长度返回字符串
[root@BJIT tmp]# more test2.txt
12345678 1234567 123456 12345 [root@BJIT tmp]# awk '{print substr($1,1,3)}' test2.txt 123 123 123 123 [root@BJIT tmp]# awk '$1==12345678 {print substr($1,1,5)}' test2.txt 12345 [root@BJIT tmp]# awk '$1==12345678 {print substr($1,3,5)}' test2.txt 34567 [root@BJIT tmp]# echo 12345678 | awk '{print substr ($1,3,6)}' 345678
字符
[root@BJIT tmp]# awk 'BEGIN {print "AtBnCtD"}'
A B C D
删掉每行的最后一个字符
awk -F'|' '{print $1"|"$2"|"$3"|"$4}' filename
sed 's/.$//g' filename
源文件:
cat filename
1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
将其中的空格都以tab键替换
awk '{print $1"t"$2"t"$3"t"$4}' filename
awk 'BEGIN {OFS="t"}{print $1,$2,$3,$4}' filename (责任编辑:IT) |