linux命令awk的一些常用技巧


awk

awk是强大的文本处理工具,既可以应对文本分割,也可以对数据进行统计,上手后十分方便快捷
这里简单记录一下使用心得和技巧,以备不时之需

内置变量

awk中的若干内置变量可以直接在脚本中使用而不需要声明,其中一部分可以直接使用option设置来修改分割方式

  • RS(record-separator) /FS(filed-separator)
    这两个是分割控制符,用来控制record和field的分割方式,默认RS为换行FS为空格。
    对应到脚本中,默认循环遍历对应的每一个record,输出的$1$2对应的是每个record的filed。
    其中FS最常用可以使用-F直接指定,如果是多种分割符的话用方括号括起来中间的每个字符都是分割符(这里可. 能是类似正则方式表达,具体还不太确定待考证)
awk -F"[|.,]" '{print $2, $4, $NF}' xxxx.log
  • ORS(output-record-separator)/OFS(output-filed-separator)
    与之相对应的还有输出的分割(叫连接更好点)控制符。
    其中OFS是用在print多项时候起作用
    这四个都是可以在option中赋值修改的

  • NR(number-of-record) NF(number-of-field)
    两者分别表示当前的record的编号和当前record分割后有多少field(也可以理解为field编号)
    这两个全部都是从1开始计数
    另外还有一个FNR,是在多个文件被awk处理时,表示record在其文件内的编号,NR表示的是全局的编号

参数

函数

排序函数

脚本中可以直接使用字典不用先定义,然后有两个排序函数可以完成对字典的排序
length=asort(ori, dest)
其中length返回的是排序后的数量,ori是传入的字典dest是排序后的字典,两个函数都是这么使用
asort 对value排序(可以数字排序)
排序后的新字典是以 编号->value 的形式存在,所以会丢失key的内容
asorti 对key排序(字符串排序)
排序后的字典的key的顺序就是排序后的顺序
两者排序后都应该使用for(i=1;i<length;i++)的方式遍历,for in的结果是无序的

清屏函数fflush

在脚本内使用fflush();函数清掉缓冲区输出

字符串分割

`split($2, tmp, ",")` 把第二个字段按照逗号分割,并将结果存入tmp数组,不改变原字符串$0

正则替换

`sub(/regix/ , "|", $2 )` 在第二个字段中使用regix正则匹配,并将匹配到的第一个替换为竖线,全部替换使用gsub函数

正则提取

`match($2, /regix/, tmp)` 从第二个字段中获取正则匹配上regix的部分存入数组tmp

参考链接
match

脚本部分

脚本三段

‘BEGIN{} {} END{}‘
BEGIN和END分别表示后面跟的大括号的内容为 遍历前 遍历后 执行,只执行一次
中间单独的大括号为遍历循环的整体,里面的内容会执行NR次
对于分割后的内容用$1 $2 $3 … 来表示第几个field,特殊的$0表示完整的当前record

数组删除元素

使用delete关键字可以删除数组中的一个元素

输出清屏

使用system("clear")来刷新terminal输出屏幕
可以用system()调用Linux的命令

输出日期时间

print strftime("%D %T",systime());

格式化字符串

printf换成sprintf可以实现 并且格式化后的字符串不是输出而是作为返回值返回

ret = sprintf("%s\n", str);

格式化输出

可以使用printf(),与c语言里的printf几乎完全一样的格式化方式很容易上手。

重定向&&管道

管道可以直接加双引号使用,但是注意需要关闭管道

参考链接
参考链接

实现sort排序的一种思路

参考链接


最后放两个例子,可以从中捞点干货例子

竖列求和

#统计当前目录下压缩文件和普通文件
ls -l |grep "tar\.gz" 
ls -l |grep -v "tar\.gz" 
#grep 最好加双引号并加上转义
[root@10-19-60-16 trafficdatapush_data]# ls -l |grep "tar\.gz" | head -5
-rw-r--r-- 1 root root          45 Apr 12 13:16 20180930_11.test.result.tar.gz
-rw-r--r-- 1 root root     4368364 Apr 12 14:07 20181011_09.onlined.result.tar.gz
-rw-r--r-- 1 root root    37920105 Apr 12 14:07 20181011_10.onlinec.result.tar.gz
-rw-r--r-- 1 root root     3835136 Apr 12 14:07 20181011_10.onlined.result.tar.gz
-rw-r--r-- 1 root root    91688929 Apr 12 14:07 20181011_10.test.result.tar.gz
 
#要统计总大小,第五列求和
 ls -l |grep "tar\.gz" |awk -F " *" '{sum+=$5; print $5","sum} END {print sum}'
# -F“ *” 指定分隔符,多个连续空格为分隔符,不然会严格一一个空格分割
# '....'单引号中是具体操作
# {sum+=$5; print $5","sum}  对于每一行sum+=第五列($0是完整的当前行) 
# END {print sum} 最后所有行结束之后输出sum

日志的耗时统计

# ori_data
cat $1| egrep "^2021-03-08 20" | grep -v "load scene\|request logstr\|get_flow\|load_flow_info\|finish reload\|infostream_data_manager\|book_column_cache" |awk -F"[|.,]" '{print $2, $4, $NF}' >$2.ori 


# new file
echo "" > $2.ret

# task cost avg
echo "sum count avg name"| awk 'END{printf("%10s, %10s, %7s, %s\n", $1,$2,$3,$4)}' >> $2.ret
cat $2.ori |awk -F" "  'BEGIN{OFS="\t"} {cnt[$1]++;sum[$1]+=$3;} END{for (k in cnt){printf("%10d, %10d, %7.3f, %s\n", sum[k], cnt[k], sum[k]/cnt[k], k)} }' >> $2.ret
echo -e "\n\n"

# each task detail
tasks=`cat ${2}.ori |head -100| awk '{print $1}'|sort|uniq|xargs`
for task in ${tasks[*]} ;do
    echo -e "\n${task}"
    cat $2.ori | grep $task |awk 'BEGIN{
        max=0;
        min=999;
    }
    {
        if($3>max)max=$3;
        if($3<min)min=$3;
        range=int(($3)/10);
        cnt[range]++;
        total++;
        keys[range]=range;
    }
    END{
        l=asort(keys, keys);
        printf "lsum_pct|";sum=0;
        for(i=1;i<=l;i++){sum+=cnt[keys[i]];printf("%7.3f%% ", sum/total*100)};print "";
        printf "percent |";
        for(i=1;i<=l;i++){printf("%7.3f%% ", cnt[keys[i]]/total*100)};print "";
        printf "count   |";
        for(i=1;i<=l;i++){printf("%8d ", cnt[keys[i]])};print "";
        printf "range   |";
        for(i=1;i<=l;i++){printf("%7d+ ", keys[i]*10)};print "";
        printf("max cost:%4d, min cost:%4d", max, min);
        print "";
    }' >> $2.ret
done
echo -e "\n\n"
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值