本文谢绝任何形式的转载,谢谢~
Linux下有众多shell命令,合理的利用可以简化工作、提升效率。
日志分析始于文本处理,与之相关的最为重要的命令个人首推grep、awk、sed~
GREP
相较于awk和sed,grep在日常工作中的应用更为普遍,使用频度颇高的命令组如"ps –ef | grep ***”,
从该命令组不难看出,grep具有文本过滤的能力。
Grep诞生以来有三个大的分支,Linux下该命令则几乎涵盖了所有分支的功能。
详细全面的介绍可以参阅相关文档,在这里,我想着重提一下 -m, -h以及-c。
-m 这是一个非常实用的功能,当我们只需要检查是否存在满足匹配,可以使用该参数;当达到限定数目后,则遍历中止。
-h 检索多文件时,结果集默认会显示文件名,这在有些场合并不必要甚至多余,使用该参数可以满足需求。
-c 效果相当于 “grep *** | wc –l”,效率大大优于前者;事实上,应当避免使用 "...|grep xxx|wc -l"这类低效操作。
最后值得一提的是,grep命令具有返回值,这在编写自动化脚本时有一定的使用价值。
相关测试代码:
[zhongming@oser116 ~]$ cat testGrep |
Awk不只是个命令,它还是一门编程语言,其高效和强大已经为历史所证明。
Awk的特别在于,你可以用它简单的写上一行完成一段逻辑,也可以用它构建出成百上千(当然可以更多)行的复杂工程。
Awk让人称道的是它的高效,曾有资深的专家试图使用C语言重新实现awk的功能,结果数万行的代码运行结果,效率提升微乎其微~
在这里,和其后的sed一样,本文不拟也不可能对awk作出完整的介绍,但即使是其最简单的应用,也能够为我们日常工作提供极大的便利。
Awk基本语法和常用参数:
awk '{pattern + action}' {filenames} Usage: awk [POSIX or GNU style options] -f progfile [--] file ... POSIX options: GNU long options: -f progfile --file=progfile 独立成文件的脚本体 -F fs --field-separator=fs 字段拆分符(集) -v var=val --assign=var=val 外部变量传递 |
Awk常用内置参数:
变量 | 描述 |
$n | 当前记录的第n个字段,0时显示所有 |
FILENAME | 当前处理文件名 |
FNR | 当前文件已处理的记录数 |
NR | 已处理的记录数 |
NF | 当前记录字段数 |
$array$ | 自建数组,名称自定义 |
以上抽列了awk最基本的命令参数和内置参数,简单做下说明:
-f 简而言之就是将’’之间的script主体独立成文件持久,可以实现脚本的复用,任何编程语言都会应用此理念,不必多言。
-F 最最基础的参数,支持正则表达式,可以指定单个或多个分隔字符。
-v awk中引用外部变量的诸多方法中,最为直观,最具美感的一种方式,需要指出的是,一组变量紧跟一个-v。
NF 返回当前记录在拆分规则下的字段数。
$n 有效范围是所有不大于NF的自然数,其中$0表示整条记录;顺带说一下,awk中内置或者自建的数组,下标都从1开始编号。
FNR/NR 理解这两个参数的关键在于理解awk的工作机制——行(记录)处理模式:
awk对文本按记录拆分规则(默认为行)逐次处理,在处理多文件时,FNR和NR则会出现差异,
利用这一差异可以实现自动化处理,下面的例子可以参考。
FILENAME,返回当前处理文件名,对应命令行中的文件输入,输出报表时有一定的应用价值。
$array$,自定义的数组,awk中的数组支持字符串的下标,可以近似理解为HASH。
`awk -F '\t' -v len=$pool_len -v ver=$list_ver' FNR==1{i++}index($1,ver){ if(i<=len){a[$2]=1} else if(i==len+1){ if(!b[$2]&&!a[$2]){ new++; b[$2]=1; } }else if(i==len+2){ if(!c[$2]&&!a[$2]){ lost++; c[$2]=1; } } }END{ print new+0,length(b),lost+0,length(c) }' ${file_list[@]:1:$pool_len} ${file_list[0]} ${file_list[$((pool_len+1))]}` |
此为一脚本片断,截取了主体逻辑的awk部分,片断外定义了数组file_list和变量pool_len。
其中file_list存放了待处理的文件列表,pool_len为可定制的池长度。处理逻辑为:
遍历所有文件,构建UID池,对新进日和流失日中不属于池的UID进行计数,遍历结束后输出计数。
“FNR==1{i++}”的作用为每一个处理的文件进行编号,从而根据编号(可以理解为文件列表中的次序)实现不同的处理逻辑。
这个用法并不严谨,不过在本问题里,风险是可以预见和规避的。
有关FNR,更为常见的应用是和NR结合,区别待处理的两个文件,代码形如:NR==FNR{…}NR>FNR{…}。
最后,目前网上通行的awk示例多为文本合并或比较,此处不再重复,本质上这类问题的处理原则为:
抽取共有的部分为KEY做为自建数组的下标,需要比较或变更的值做为Value,按实际的需求组合逻辑、操作数组即可。
和awk一样,Sed处理机制也为行模式(多行模式本文不拟涉及)。调用形式和awk类似
Sed基本语法和常用参数:
sed [options] 'command' file(s) sed [options] -f scriptfile file(s) Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]... -e script, --expression=script 允许多台编辑 -f script-file, --file=script-file 同awk该参数 -n, --quiet, --silent 静默模式,输出结果须显示指定(p)才打印, -i[SUFFIX], --in-place[=SUFFIX] 处理结果修改至原文件 -r, --regexp-extended 使用扩展的正则表达式 |
常用Command列表:
d 从模板块(Pattern space)位置删除行。 n 读取下一个输入行,用下一个命令处理新行。 p 打印模板块的行。 q 退出Sed。 = 打印当前行号码。 s/re/string/[gp] 替换操作,g表全局,p为打印指示。 |
示例:
1. 删除 d命令
[zhongming@oser116 ~]$ cat 1.sql 1 2 3 [zhongming@oser116 ~]$ sed '2d' 1.sql 1 3 [zhongming@oser116 ~]$ cat 1.sql 1 2 3 [zhongming@oser116 ~]$ sed -i '2d' 1.sql [zhongming@oser116 ~]$ cat 1.sql 1 3 |
剔除文本第二行,将结果返回给终端,不改变文件内容。
使用-i参数时将结果修改至原文件。
2. 替换 s命令
[zhongming@oser116 ~]$ cat 1.sql |
匹配到1时替换为自身+a,&表示替换字符串中被找到的部份。
3. 其它
[zhongming@oser116 ~]$ cat 1.sql 1 1 1 1 1 1 3 3 3 3 3 3 [zhongming@oser116 ~]$ sed -e 's/1/a/' -e '/3/d' 1.sql a a a a a a [zhongming@oser116 ~]$ sed -n '2{=;p;q}' 1.sql 2 1 |
a. 多点编辑,匹配到1则替换为a,匹配到3则删除该行
b. 打印第二行的行号,然后打印第二行内容,继而退出