天天看点

shell三剑客 grep sed awk

shell 元字符

^ 行首定位符

$ 行尾定位符

. 任意单个字符

1. 匹配前导符0到多次

.* 任意多个字符

[] 匹配指定范围内的一个字符

[-] 匹配指定范围内的一个字符

[^] 匹配不在指定组内的字符

\ 用来转义元字符 (” “” )

\< > 词首和词尾定位符

() 匹配稍后使用的字符的标签

x{m} 字符x重复出现m次

x{m,} 字符x重复出现m次以上

x{m,n}字符x重复出现m到n次

2. 匹配一个或多个前导字符

? 匹配零个或一个前导字符

a|b 匹配a或b

grep

过滤,查找文档中的内容 :grep 选项 匹配模式  文件

1. grep 支持基本正则

2. egrep 支持扩展正则

3. fgrep 不支持正则

返回值:

  • 0 表示找到内容
  • 1 表示没找到内容
  • 2 表示找的目录不对

常用选项:

-q    静默查询结果

-v    取反查询

-R    递归查询目录下的文件

-A2   显示查询内容及后2行

-B2   显示查询内容及前2行

-C2   显示查询内容及前后各2行

egrep -l 只显示有查询内容的文件名

egrep -n  查询结果带行号

sed 流编辑

sed 是一种在线的、非交互式的编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。

文本文件->“模式空间”(pattern space)->屏幕

逐行处理

内容未变

编辑文件

格式:sed 选项 [模式]命令 文件

常用选项:

-r  支持正则

-i  直接修改文件内容

-n  静默输出

常用命令:

p  打印

d  删除

s  替换

c  整行替换

a  追加

i  插入

r  读文件

w  写文件

返回值:只有0,不管对错

awk

用来切割和统计

语法:awk 选项 ‘BEGIN{} {} END{}’ 文件名

原理:

(1)awk使用一行作为输入,并将这一行赋给内部变量$0,每一行也可称为一个记录,以换行符结束

(2)然后,行被:(默认为空格或制表符)分解成字段(或域),每个字段存储在已编号的变量中,从$1开始,

最多达100个字段

(3)awk输出之后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔

成字段并进行处理。该过程将持续到所有行处理完毕

模式和动作:

任何awk语句都由模式和动作组成。模式部分决定动作语句何时触发及触发事件。处理即对数据进行的操作。如果省略模式部分,动作将时刻保持执行状态。

模式可以是任何条件语句或复合语句或正则表达式。

模式包括两个特殊字段 BEGIN和END。

BEGIN语句使用在任何文本浏览动作之前

END语句用来在awk完成文本浏览动作后打印输出文本总数和结尾状态。

条件表达式: awk -F: ‘{ if() {} }’ /etc/passwd

[root@localhost ~]# awk -F: '{ if($3<5) {print $0} }' /etc/passwd
root:x:::root:/root:/bin/bash
bin:x:::bin:/bin:/sbin/nologin
daemon:x:::daemon:/sbin:/sbin/nologin
adm:x:::adm:/var/adm:/sbin/nologin
lp:x:::lp:/var/spool/lpd:/sbin/nologin
           

循环:

awk ‘BEGIN{for(i=1;i<=5;i++){print i} }’

awk ‘BEGIN{ i=1; while(i<=10){print i; i++} }’

数组:

awk -F: ‘{username[x++]=$1} END{for(i in username) {print i,username[i]} }’ /etc/passwd

常用案例:

  1. 统计/etc/passwd中各种类型shell的数量
    awk -F: ‘{shells[$NF]++} END{ for(i in shells){print i,shells[i]} }’ /etc/passwd
  2. 网站访问状态统计 <当前时实状态 netstat>
    netstat -ant |grep :80 |awk ‘{access_stat[$NF]++} END{for(i in access_stat ){print i,access_stat[i]}}’
  3. 统计当前访问的每个IP的连接数量 <当前时实状态 netstat,ss>
    ss -an |grep :80 |awk -F”:” ‘!/LISTEN/{ip_count[$(NF-1)]++} END{for(i in ip_count){print i,ip_count[i]}}’ |sort -k2 -rn |head
  4. 统计Apache/Nginx日志中某一天的PV量  <统计日志>
    grep '07/Aug/2012' access_log |awk '{ips[$1]++} END{for(i in ips){print i,ips[i]} }' |awk '$2>100' |sort -k2 -rn