`
z1041950008
  • 浏览: 16712 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

记录我的第一个awk脚本-日志统计

 
阅读更多

项目中需要一个统计接口量的脚本,于是尝试着写了第一个awk脚本。

过程不轻松,但是写完了觉得很爽。哈哈

-----------------------------------------------------------------------------------------------------------------------------------

 

#########################################
####思路:
####1 按行读取,需要判断每条记录的归属线程,并缓存起来,
####2 每个线程的记录打印都是有顺序的,输入报文>异常>输出报文
####3 将输入报文覆盖缓存,当第一次读取到Exception时,认为异常开始,将最近一次的输入报文打印,
####4 异常全部打印完毕后,打印输入报文
####注意:
####所有的缓存都是按照线程名称做得,类似于线程变量,互不影响,通过数组实现
####
####使用:
####1 THREAD_KEY需要替换,不同的日志不一样
####2 INPUT_KEY和OUTPUT_KEY如不同也替换
####3 isExclude函数,如有需要可以修改不同的排除条件
#########################################
BEGIN{
#	变量是不带双引号的,变量值需要带着双引号
	THREAD_KEY = "@HttpThreadPool";
	INPUT_KEY = "输入报文";
	OUTPUT_KEY = "输出报文";
	ROW_CACHE = "ROW_CACHE";
	THREAD_NAME = "THREAD_NAME";
	FILE_NAME = "XXXXX";
}

#获取线程名
function getThreadName(str){
#       线程名称开始索引
        THREAD_KEY_END_INDEX = index($0, THREAD_KEY);
        if(THREAD_KEY_END_INDEX > 0){
#               获取线程名称
                THREAD_NAME_T = substr($0, THREAD_KEY_END_INDEX - 9, 9 );
                if(THREAD_NAME_T != "") {
                        THREAD_NAME= THREAD_NAME_T;
                }
        }
	return THREAD_NAME;	
}

#判断此行是否需要排除,后续可增加条件
function isExclude(str){
	return index(str, "通过HTTP方式获取缓存失败");
}

#判断不需打印输入输出报文的异常
function needRequestMsg(str){
	return index(str, "未找到相应文件")  + index(str, "没有生成密钥");
}


{
	if(FILE_NAME != FILENAME){
		if(FILE_NAME != "XXXXX" ){
			printf("+++++++++++++++++文件处理完成[%s]+++++++++++++++++++\n", FILE_NAME);
		}
		printf("+++++++++++++++++开始处理文件[%s]+++++++++++++++++++\n", FILENAME);
		FILE_NAME = FILENAME;
	}

#	获取线程名	
	THREAD_NAME = getThreadName($0);	

#	处理不需要打印输入输出报文的部分
	if(needRequestMsg($0) > 0){
                printf("---------Begin Exception-%s-[%d]------------\n", THREAD_NAME, ++THREAD_EXCEPTION_NUM[THREAD_NAME]);		
		printf("%s\n", ROW_CACHE);
		printf("%s\n", $0);
		getline ;
		while (index($0, "at ") > 0 && index($0, "(") > 0 ){
			printf("%s\n", $0);
			getline;
		}
                printf("---------End Exception-%s-[%d]------------\n", THREAD_NAME, THREAD_EXCEPTION_NUM[THREAD_NAME]);
	}


#	当此行中有关键字Exception	
	if(index($0, "Exception") > 0 && isExclude($0) == 0) {
#		BEGIN_EXCEPTION_FLAG是一个key为线程名称的数组缓存,记录当前线程是否开始一个Exception
                if((BEGIN_EXCEPTION_FLAG[THREAD_NAME] == "" || BEGIN_EXCEPTION_FLAG[THREAD_NAME] == "0")){
#			当没有开始时,将缓存的输入报文打印,同时记录状态为已开始
			BEGIN_EXCEPTION_FLAG[THREAD_NAME] = "1";
		}
#		当此行没有线程名称,且不存在Caused by关键字时,说明为异常被换行,打印上一行
		if(index($0, THREAD_NAME) == 0 && index($0, "Caused") == 0 && index($0, "at ") == 0){
		 	BODY_EXCEPTION[THREAD_NAME] = sprintf("%s\n%s", BODY_EXCEPTION[THREAD_NAME], ROW_CACHE);
		}
#		所有Exception的行都打印
		BODY_EXCEPTION[THREAD_NAME] = sprintf("%s\n%s", BODY_EXCEPTION[THREAD_NAME], $0);
	}
#	存在关键字"at "的行打印
	if(index($0, "at ") > 0 && index($0, "(") > 0){
		BODY_EXCEPTION[THREAD_NAME] = sprintf("%s\n%s", BODY_EXCEPTION[THREAD_NAME], $0);
	}
#	当此行中存在输出报文关键字,且已经开始一个Exception,打印输入报文,Exception体,输出报文
	if(index($0, OUTPUT_KEY) > 0 && BEGIN_EXCEPTION_FLAG[THREAD_NAME] == "1"){
                printf("---------Begin Exception-%s-[%d]------------\n", THREAD_NAME, ++THREAD_EXCEPTION_NUM[THREAD_NAME]);
		printf("%s\n", INPUT_MSG[THREAD_NAME]);
		printf("%s\n", BODY_EXCEPTION[THREAD_NAME]);
		
#		有可能输出报文有换行,目前处理换行一次的情况,判断行尾是"?>"时,读取下一行并打印
		printf("%s", $0);
		if(substr($0, length($0)-1) == "?>"){
                        getline t;
                	printf("%s\n", t);
		} else {
			print "\n";	
		}
		
		printf("---------End Exception-%s-[%d]------------\n", THREAD_NAME, THREAD_EXCEPTION_NUM[THREAD_NAME]);
#		输出报文已打印,Exception结束
		BEGIN_EXCEPTION_FLAG[THREAD_NAME] = "0";
		BODY_EXCEPTION[THREAD_NAME] = "";
		INPUT_MSG[THREAD_NAME] = "";
	}
#	当此行中存在输入报文关键字时
	if(index($0, INPUT_KEY) > 0){
#		缓存此行,并判断是否存在报文换行的情况
		INPUT_MSG[THREAD_NAME] = $0;
		if(substr($0, length($0)-1) == "?>"){
			getline t;
			INPUT_MSG[THREAD_NAME] = sprintf("%s%s", INPUT_MSG[THREAD_NAME], t);
		}
	}
#	缓存当前行
	ROW_CACHE = $0;
}

END{
	printf("+++++++++++++++++文件处理完成[%s]+++++++++++++++++++\n", FILENAME);
}

 

0
0
分享到:
评论

相关推荐

    AWK 教程 - v1.0.pdf

    **第一章:概述** 本章将介绍AWK的基本概念,包括它的起源、用途以及与其他文本处理工具(如grep、sed)的区别。AWK的工作原理是逐行扫描输入文件,对每一行执行一系列预定义的动作。这一特性使得AWK非常适合处理...

    AWK脚本开发教程(深入)

    如果想打印出第一个和第三个字段,可以使用`'{ print $1 $3 }'`,但请注意,相邻的字符串不会自动添加空格,需要显式地插入,如`'{ print $1 " " $3 }'`。 在AWK中,字段可以通过数字索引引用,如`$1`、`$2`等,也...

    AWK脚本学习文档 Linux

    这里`$1`表示第一个字段,`$2`表示第二个字段,以此类推。 **三、模式匹配** AWK支持两种模式匹配:行模式和记录模式。行模式基于行内容进行匹配,如: ```awk /regex/ { action } ``` 记录模式则基于行号或其他...

    awk-培训.docx

    - `-F`选项可以指定分隔符,如`awk -F":" '{print $1}' /etc/passwd`会打印`/etc/passwd`文件中每一行的第一个字段,即用户名。 - `$1`、`$3`等表示字段,多个连续的空格或制表符被视为一个分隔符。 - 若要合并字段...

    Linux下对NS2项目的仿真分析全过程(从tcl脚本-awk文本处理-gnuplot)

    例如,`plot 'datafile' using 1:2 with lines`将根据"datafile"中的第一列作为x轴,第二列作为y轴绘制线条图。 在NS2仿真的整个流程中,TCL脚本定义了网络行为,AWK处理了输出的数据,而GNUPLOT则将这些数据转化为...

    第二十四章:shell脚本-正则、grep、sed、awk三剑客1

    ### 第二十四章:Shell 脚本 - 正则、grep、sed、awk 三剑客 #### 一、正则表达式及 grep **1. 概述** 正则表达式是一种强大的文本处理工具,它能够帮助用户方便地进行字符串的搜索、替换等操作。在 Linux 系统中...

    AWK语言学习资料--基础知识

    - 使用AWK可以方便地处理文件中的特定字段,如`print $1,$2`表示打印第一和第二个字段。 - 支持脚本形式的AWK,通过`-f`选项指定脚本文件,如`awk -f test.awk /etc/passwd`。 3. **条件判断与循环** - AWK支持...

    awk学习笔记,从论坛整理而来

    这里的模式是默认的(即每一行),动作是打印第一个字段 `$1`。 ### 3. 域与记录 在 `awk` 中,文本被分割成记录(通常是行)和域(由分隔符分开的部分)。如果没有指定 `-F`,默认的分隔符是空格或制表符。例如,...

    awk命令详解 包括详细的组合结构

    使用`$n`来引用域,如`$1`代表第一个域,`$0`代表整个记录。`print`命令常用于输出域内容,例如`print $0`打印整行,`print $1,$4`打印第一个和第四个域。 4. **动作和输出管理** - `print`命令可以输出指定的域,...

    Linux实战awk详解

    例如,"BEGIN"模式在处理任何输入前执行,"END"模式在处理完所有输入后执行,而"{print $1}"这样的模式-动作对会打印每行的第一个字段。 awk还提供了内置变量,如NR(已读取的行数)、NF(当前行的字段数)和FS...

    awk思维导图-jpeg单文件

    例如,`print $1`会打印每一行的第一个字段。 3. **条件测试**:awk支持条件语句如`if...else`,可以根据某个条件执行不同的动作。例如,`if ($2 > 10) {print $0}`会打印所有第二个字段大于10的行。 4. **循环...

    AWK实例教程 AWK实例教程中文版

    例如`awk -F ":" '{print $1}' /etc/passwd`会打印出/etc/passwd文件中每一行的第一个字段。 - **连接字段**:可以通过直接连接字符串的方式输出多个字段。例如`awk -F ":" '{print $1 $3}' /etc/passwd`将输出...

    AWK入门教程和实战案例

    - **分解记录**:使用内置变量`NF`表示当前记录的字段数量,`$n`引用第n个字段,如`$1`是第一个字段,`$0`代表整个记录。 3. **输出** - **print**:AWK中最常用的输出函数,用于打印字段或表达式的结果,默认用...

    实战Shell脚本—sed,awk使用

    例如,`awk -F ',' '{print $1}' file.csv`会打印`file.csv`中所有行的第一列,其中`-F ','`设定了字段分隔符为逗号。 结合这两个工具,开发者可以在Shell脚本中实现更复杂的数据处理任务。例如,可以先用`sed`...

    AWK-学习笔记(共享)

    基本形式为`awk 'program' file1 file2 ...`,其中`program`是AWK脚本。 4. **AWK的语法**: - `pattern {action}`是AWK的基本结构,表示当行匹配`pattern`时执行`action`。 - 如果没有指定`pattern`,则`action`...

    SED与AWK 高清第三版

    《SED与AWK 高清第三版》是一本专注于Linux系统中强大文本处理工具sed和awk的教程。在Linux环境中,sed和awk是不可或缺的工具,它们能够高效地处理大量文本数据,进行搜索、替换、格式化等操作,极大地提高了运维...

    awk学习awk学习awk学习awk学习

    1. **日志文件分析**: awk经常用于分析和处理大量的日志文件,帮助快速查找特定的信息或统计关键数据。 2. **配置文件处理**: 对于需要解析和修改的配置文件,awk能够轻松实现自动化处理。 3. **文本数据处理**: 如...

    AWK单行脚本快速参考.doc

    - `[ABC][DEF]`:两个方括号表示前后两个字符都要匹配,第一个是`[ABC]`的任何一个,第二个是`[DEF]`的任何一个。 2. **AWK算术运算符** - `^`或`**`:幂运算,例如`2^3`等于8。 - `%`:求模运算,如`7%3`等于1...

Global site tag (gtag.js) - Google Analytics