转自:http://blog.csdn.net/tianmohust/article/details/6970271
awk命令的一般形式:
awk 'BEGIN {actions}
pattern1 {actions}
pattern2 {actions}
...
patternN {actions}
END {actions}' input-filename
其中,BEGIN{actions} 和 END {actions}是可选的。
awk的执行过程如下:
1,如果存在BEGIN,awk首先执行它指定的actions。
2,awk从输入中读取一行,称为一条输入记录。
3,awk将读入的记录分割成个字段,并将第一个字段放入变量$1中,第二个放入变量$2中,依次类推。$0表示整条记录;字段分隔符可以通过选项-F指定,否则使用默认的分隔符。
4,把当前输入记录依次与每一个语句中pattern比较;如果相匹配,就执行相应的actions;如果不匹配,就跳过相应的actions,直到完成所有的语句。
5,当一条输入记录处理完毕后,awk读取下一行,重复上面的处理过程,直到所有输入全部处理完毕。
6,如果输入是文件列表,awk将按顺序处理列表中的每个文件。
7,awk处理完所有的输入后,若存在END,则执行相应的actions。
awk常用的内置变量
变量 说明
NF 当前记录中的字段数
NR 当前记录数
FS 字段分隔符(默认是一个空格)
RS 记录分隔符(默认是一个换行符)
OFS 输出字段分隔符(默认是一个空格)
ORS 输出字段分隔符(默认是一个换行符)
ORSIGNORECASE 如果是真,则进行忽略大小写的匹配
awk使用实例:
# 使用awk打印字符串
# awk 'BEGIN { print "hello" }'
#hello
# awk 'BEGIN { print 1.05+2e/10.5+2.0**3-3.14 }'
# cat test.txt
#显示输入文件的内容
# awk '{ print }' test.txt
#使用正则表达式匹配行,{actions}省略时表示{print}
# awk '/F[12].*/' test.txt
#使用正则表达式匹配行,并打印匹配的第一和第三列(域或字段)
# awk '/F[12].*/ { print $1,$3 }' test.txt
#更改字段分隔符为!,执行上面的操作
# awk -F\! '/F[12].*/ { print $1,$3 }' test.txt
#使用空格或!作为字段的分隔符(正则表达式[ !])
# awk -F '[ !]' '/F[12].*/ { print $1,$3 }' test.txt
#使用awk内置的取字串函数提取输入文件中的手机号
# awk -F '[ !]' ' { print substr($3,6) }' test.txt
#使用关系表达式书写模式,打印所奇数行
# awk 'NR % 2 == 1' test.txt
#使用关系式书写模式,打印所有奇数行的第1和第3字段
# awk 'NR % 2 == 1 { print $1,$3 }' test.txt
#打印输入文件的总行数,类似于 wc -l test.txt
# awk 'END {print NR}' test.txt
# awk '{ print NR }' test.txt //从1到最后一行
#为每一记录前面添加行号,类似于 wc -n test.txt
# awk '{ print NR,$0 }' test.txt
#为每一记录前面添加行号,并使用制表符作为行号和记录的间隔符
# awk '{ print NR "\t" $0 }' test.txt
#为每行前面加上指定的字符串,并且输入到tmpnum.txt
# awk '{print "tianmo:" $0}' num.txt > tmpnum.txt
#把当前目录下面后缀名为.txt的文件,添加前缀,并且输入到tmpnum.txt
# awk '{print "tianmo:" $0}' *.txt > tmpnum.txt
注意以下命令的灵活应用
#awk 'NR % 2 == 1' a.txt b.txt > d.txt
#awk 'NR % 2 == 1' *.txt > d.txt
#awk '{print "tianmo: >" $0}' *.txt > tmpnum.txt
#awk '{sum += $5}; END {print sum}' num.txt //求第五个字段的和
另外,在awk语句里面可以根据条件进行数据筛选,一般是跟字段或字段的某些数,字符进行比较,进而再进行具体的操作。
下面再给出一些awk和其他命令使用的例子
#提取文件中的手机号
# cat test.txt | awk -F\! '{ print $3 }' | awk '{ print $1 }' | cut -c6-16
#以文件修改顺序生成当前目录下带有时间的文件名
# ls -aldt * --time-style='+%F_%H:%M' | awk '{ print $7 "--" $6 }'
#计算当前目录中所有12月份创建的文件的字节数
# ls -l | awk ' $6 == "Dec" { sum += $5}; END { print sum }'
#显示当前所有的登录用户和其使用的终端
# who | awk '{ print $1 "\t" $2}'
# df -hPT -x tmpfs //文件设备的详细信息
#显示ifconfig -a的输出中以单词开头的行
# ifconfig -a | grep '^\w'
#显示除了lo之外的所有网络接口
# ifconfig -a | grep '^\w' | awk '!/lo/{print $1}'
#匹配inet的行,以分号为字段间隔符打印第二个字段
# ifconfig eth0 | awk -F\: ' /inet/ { print $2}'
# ifconfig eth0 | awk -F\: ' /inet/ { print $2}' | awk '{print $1}'
# ifconfig eth0 | grep 'inet'
#以一个或多个空格 或:作为字段分隔符(正则表达式' +|:')
# ifconfig eth0 | grep 'inet' | awk -F ' +|:' '{print $4}'
#以一个或多个空格 或 一个或多个:作为字段分隔符(正则表达式'[ :]+')
# ifconfig eth0 | grep 'inet' | awk -F '[ :]+' '{print $4}'
#删除所有名为foo的进程
# kill 'ps ax | grep 'foo' | grep -v 'grep' | awk '{print $4}''
#查看Apache的并发请求数及其TCP连接状态
# FROM : http://blog.s135.com/read.php/269.htm
# netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
//NF 是当前记录的字段个数, 使用$NF可以实现每个记录的最后一个字段 就和$6一样
1. 应用场景
在 linux 下有时在处理配置文件是,需要对一个文本块进行处理,此时使用 awk 的强大功能。文本块的格式是如下:
[section1]
tag1 = value_a
tag2 = value_b
tag3 = value_c
[section 2]
tag4 = {
subtag1 = subtag_value_a
subtag2 = subtag_value_b
subtag3 = subtag_value_c
}
[section 3]
tag6 = {
subtag1 = subtag_value_a
subtag2 = subtag_value_b
}
现在有个需求,需要在[section 2] 这个文本块加入tag5={key=vaule}( 类似于tag4 的格式) 这种形式的属性。当然还需要对其进行修改和删除。下面就是示范使用awk 来进行处理。
1.1. 增加
假设现在要进行添加操作,首先必须要检查tag5 这个文本块是否存在,如果不存在就添加。awk 编程如下:
- awk –v TAGVALUE1=vaule_a –v TAGVALUE2=vaule_b '{
- if ($0 ~ /^/[section 3/]$)
- print "tag5 = {/nsubtag1= " TAGVALUE1 "/nsubtag2= " TAGVALUE2 "/n} "
- print #其他保持不变
- }' a.conf
结果如下:
[root@local~]#cat a.conf ·
…
[section 2]
tag4 = {
subtag1 = subtag_value_a
subtag2 = subtag_value_b
subtag3 = subtag_value_c
}
tag5 = {
subtag1 = value_a
subtag2 = value_b
}
[section 3]
tag6 = {
subtag1 = subtag_value_a
subtag2 = subtag_value_b
}
1.2. 修改
假设现在要进行修改操作( 把tag5 中的 subtag2 的值修改为 vaule_bb ) ,首先必须要检查tag5 这个文本块是否存在,如果存在就修改。awk 编程如下:
- awk –v TAGVALUE2=vaule_bb '{
- if ($1== tag5) { #找到tag5这个文本块
- do{
- getline; #得到$0
- if ($1 == "subtag2"){
- print "subtag2 = " TAGVALUE2
- continue
- }
- print $0 #其他保持不变
- }while($1 != "}")
- }
- print $0 # 其他保持不变
- } ' a.conf
结果如下:
…
[section 2]
tag4 = {
subtag1 = subtag_value_a
subtag2 = subtag_value_b
subtag3 = subtag_value_c
}
tag5 = {
subtag1 = value_a
subtag2 = value_bb
}
[section 3]
tag6 = {
subtag1 = subtag_value_a
subtag2 = subtag_value_b
}
1.3. 删除
假设现在要进行删除操作( 把tag5 这个文本块删除 ) ,首先必须要检查tag5 这个文本块是否存在,如果存在就删除。awk 编程如下:
- awk '{
- if ($1== tag5) { #找到tag5这个文本块
- do{
- getline; #得到$0
- }while($1 != "}") #删除该块
- }
- else
- print $0 # 其他保持不变
- }' a.conf
结果如下:
…
[section 2]
tag4 = {
subtag1 = subtag_value_a
subtag2 = subtag_value_b
subtag3 = subtag_value_c
}
[section 3]
tag6 = {
subtag1 = subtag_value_a
subtag2 = subtag_value_b
}