`
jupiterpan
  • 浏览: 19909 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

grep,awk,sed 简单小结

阅读更多

本文谢绝任何形式的转载,谢谢~

 

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
a
a
a
a
b
b
b
[zhongming@oser116 ~]$ grep a testGrep
a
a
a
a
[zhongming@oser116 ~]$ grep -m 1 a testGrep
a
[zhongming@oser116 ~]$ grep -m 1 a testGrep testGrep
testGrep:a
testGrep:a
[zhongming@oser116 ~]$ grep -h -m 1 a testGrep testGrep
a
a


 

AWK

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,按实际的需求组合逻辑、操作数组即可。

 

 

 SED

和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
3
[zhongming@oser116 ~]$ sed 's/1/&a/' 1.sql
1a
3

匹配到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. 打印第二行的行号,然后打印第二行内容,继而退出

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics