Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1272476
  • 博文数量: 179
  • 博客积分: 3044
  • 博客等级: 中校
  • 技术积分: 2437
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-25 15:04
文章分类

全部博文(179)

文章存档

2021年(2)

2020年(1)

2019年(5)

2018年(13)

2017年(6)

2016年(10)

2015年(11)

2014年(11)

2013年(13)

2012年(23)

2011年(25)

2010年(2)

2008年(1)

2007年(5)

2006年(51)

awk

分类: 系统运维

2012-03-08 15:32:49

以"{"作为分割符,把符合以location开头中间有N个空格以microblog结尾进行分割,得到一段内容
 awk -v  RS="{" '/location[ ]+\/microblog/ ' microblog.conf

字符串格式显示:
30个字符位,不够用空格在前面补全
> echo abcd | awk '{printf "%-30s\n",$1}'
abcd                          
30个字符位,不够用空格在后面补全
> echo abcd | awk '{printf "%-30sddd\n",$1}'
abcd                          ddd

不限行相数据相加
awk 'BEGIN{sum=0}{for(i=1;i<=NF;i++) sum+=$i;}END{printf("sum=%d\n",sum)}' test.log
实例:
awk '{rec=$0};END {print rec}' mongocnn.txt |awk 'BEGIN{sum=0}{for(i=1;i<=NF;i++) sum+=$i;}END{printf("sum=%d\n",sum)}'


没有定义--posix或--re-interval时,不能用{n}或者{x,y}这样的语法,并且不能给{}加转义符号

[root@test187 tmp]# grep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}" txt|wc -l
14675
[root@test187 tmp]# grep -E "^([0-9]{1,3}\.){3}[0-9]\{1,3\}" txt|wc -l
0

[root@test187 tmp]# awk --re-interval '/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/{print}' txt|wc -l
14675

[root@test187 tmp]# awk '/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/{print}' txt|wc -l
0

更简单的:

[root@test187 tmp]# awk --re-interval '/^([0-9]{1,3}\.){3}[0-9]{1,3}/{print}' txt|wc -l
14675


输出文件的前10行(模拟 head -n 10 ) awk ' NR < 11 '

如前所述,这里省略了动作,即为打印输出。匹配模式是变量NR需要小于11,NR即为当前的行号。这个写法很简单,但是有一个问题,在NR大于10的时候,awk其实还是对每行进行了判断,如果文件很大,比如说有上万行,浪费的时间是无法忽略的。所以,更好的写法是

awk '1; NR = 10 { exit }'

第一句对当前行进行输出。第二句判断是不是已经到了第10行,如果是则退出。

输出文件的第一行(模拟 head -n 1 ) awk 'NR > 1 { exit }; 1'

这个例子与前一个很相似,中心思想就是第二行就退出。

输出文件的最后两行(模拟 tail -n 2 ) awk '{ y=x "\n" $0; x=$0}; END { print y }'

的确,这一句看起来确实有些别扭。第一句总是把一个在当前行前面再加上变量x的内容赋值给y,然后用x记录当前行内容。这样的效果是y的内容始终是上一行 加上当前行的内容。在最后,输出y的内容。如果仔细看的话,不难发现这个写法是很不高效的,因为它不停的进行赋值和字符串连接,只为了找到最后一行!所 以,如果你想要输出文件的最后两行,tail -n 2是最好的选择。

输出文件的最后一行(模拟 tail -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'

如果想要少执行些不必要的循环,就这样写:

awk 'NR==52 {print;exit}' 输出两次正则表达式匹配之间的行 awk '/regex1/, /regex2/' 删除所有的空行 awk NF

NF为真即是非空行。另外一种写法是用正则表达式:

awk '/./'

这个很类似grep .的思路,但是是不如awk NF好的,因为“.”也是可以匹配空格和TAB的。

在空行前加注释符 awk '{print"#"$0}' txt
sed 's/^/#/g' 
 txt
awk '$0="#"$0' txt    #好方法

打印出空行行号

awk '/^$/{print NR}' filename

同理:打印出含有字符good的行号

awk '/good/{print NR}' filename

以空格和?为分隔符                                          源文件 1111  2222?3333

#awk -F '[ ]+|?' '{print $2}'                                                                      2222


打印报告头和结尾

awk 'BEGIN {print "numA\tnumB\n------------"} {print $1"\t"$2} END {print "ENDA\t ENDB\n-----------"}' 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         
7
9
15
[root@BJIT tmp]# awk '{if($2~/a/) print $1}' test.txt
1
7

用==号匹配
[root@BJIT tmp]# awk '$1=="3" {print $0}' test.txt
3       b

匹配正则
[root@BJIT tmp]# awk '$1 ~ ".5" {print $1}' test.txt
15
[root@BJIT tmp]# awk '{if($2~/c/)print $1}' test.txt
5
15

关系匹配:
[root@BJIT tmp]# awk '$1 ~ "5|7" {print $0}' test.txt
5       c
7       a
15      c

AND匹配:
[root@BJIT tmp]# awk '$1=="5" && $2=="c" {print $0}' test.txt
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
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

域值比较(两种方法)
[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

修改数值域取值:
[root@BJIT tmp]# awk '{$1=$1-2;print $1}' test.txt
-1
1
3
5
7
13
[root@BJIT tmp]# awk '{if($1>2)($1="test"); print $0}' test.txt
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
1  a
3  b
5  c
7  a
9  b
15 c
40

将相加结果除以100                                                                                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 "A\tB\nC\tD"}'
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


awk数组的例子:

[root@test187 tmp]# more 1

info[3]:  account[1]  141

info[3]:  account[1]  109

info[3]:  account[1]  3599

info[3]:  account[1]  211

info[3]:  account[1]  37

info[3]:  account[2]  119

info[3]:  account[3]  70

info[3]:  account[3]  342

info[3]:  account[1]  8

 

[root@test187 tmp]# awk '{a[$2]+=$3}END{for (i in a)print i,a[i]}' 1|sort

account[1] 4105

account[2] 119

account[3] 412

 

解释:

a[$2]$2为数组account[1] account[2] account[3],并赋值给a

+=$3a的值等于第三域相加的值

for (i in a)ifor循环,赋予i的值为变量a,也就是account[1] account[2] account[3]

print i,a[i]:对应输入i i对应的a值的第三域相加的值




ls |awk '{printf("mv %s %s\n", $0, toupper($0))|"sh"}'

把当前目录下的所有小写文件名都改为大字文件名。


ls |awk '{printf("mv %s %s\n", $0, tolower($0))|"sh"}'

把当前目录下的所有大写文件名都改为小字文件名

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

78922422012-03-09 00:22:14

进来看看……