使用awk的NR与FNR合并两个文件
工作遇到一个需求有如下两个文件:
- file a
store.louguanstar.com 5.6.7.8
app.louguanstar.com 1.2.3.4
foo.louguanstar.com a.b.c.d
- file b
foo.louguanstar.com 1300
store.louguanstar.com 1100
app.louguanstar.com 1200
现在需要把这个文件处理为如下样式然后加上xml文件头就行,用作hadoop集群的topology文件
<node name="foo.louguanstar.com" rack="/avatar/1300"/>
<node name="a.b.c.d" rack="/avatar/1300"/>
<node name="store.louguanstar.com" rack="/avatar/1100"/>
<node name="5.6.7.8" rack="/avatar/1100"/>
<node name="app.louguanstar.com" rack="/avatar/1200"/>
<node name="1.2.3.4" rack="/avatar/1200"/>
awk可以使用自身变量NR和FNR来处理多个文件。
NR:awk开始执行程序后所读取的数据行数。
FNR:awk当前读取的记录数,FNR值小于等于NR(当awk读取第二个文件时,FNR是从0开始重新计数,而NR继续累加)。
NR==FNR:用于在读取两个或两个以上的文件时,判断是不是在读取第一个文件。
awk处理多个文件的基本语法是: awk -F分隔符 ‘BEGIN { 初始化 } { 循环执行部分 } END { 结束处理 }’ file1 file2
其中BEGIN和END可以省略,-F用来指定分割符
最后使用如下命令就可以得到上面的结果:
awk 'NR==FNR{a[$1]=$2}FNR<NR{print $1,a[$1],$2}' a b | awk '{print "<node name=\""$1"\" rack=\"/avatar/"$3"\"/>\n<node name=\""$2"\" rack=\"/avatar/"$3"\"/>"}'
后面又发现使用awk可以统计每块网卡的网速,命令如下:
tmp1=`mktemp`
tmp2=`mktemp`
/bin/cat /proc/net/dev | awk 'NR>2 {print $1" tx "$2" ,rx "$10}' |sed 's/://' >$tmp1
sleep 5
/bin/cat /proc/net/dev | awk 'NR>2 {print $1" tx "$2" ,rx "$10}' |sed 's/://' >$tmp2
echo ",
\"band_width_out\":{"
awk 'NR==FNR{a[$1]=$3}NR>FNR{print " \""$1"\":\""($3-a[$1])/5/1024"MB/s\","}' $tmp1 $tmp2
echo " },
\"band_width_in\":{"
awk 'NR==FNR{a[$1]=$NF}NR>FNR{print " \""$1"\":\"" ($NF-a[$1])/5/1024"MB/s\","}' $tmp1 $tmp2
echo " }"
rm $tmp1 $tmp2