Linux 之文本处理grep、sed、awk

1、正则表达式

    基础正则
^                 匹配文本开始    
$                  匹配文本结束
^$               匹配空行
.                   除了空字符的任意字符
\                  转义
*                  前面字符重复0到无穷次
.*                 任意字符任意次数
[]                 [abc] a或b或c
[^]              [^abc] 除abc以外的任意字符
 
扩展正则
+             前面的表达式重复1到无穷次
|             abc|def  abc或者def
()                        分组,可以用序号或取别名得到结果
{}                        用于限制次数
?                         前面的字符重复0次或1次 
反向引用              分组后可以使用序号或别名代表的结果
    注:
        1. 编写时正则表达式时,尽量使用单引号,双引号的字符会先被shell解释,可能丢失原有的含义。
        2. grep 和 sed 默认不支持扩展表达式,
                grep 需要使用 -E 参数或者直接使用 egrep
                sed 使用 -r 参数

2、grep

    一种强大的额文本搜索工具,它能使用特定模式匹配(包括正则表达式)搜索文本,并默认输出匹配行
grep 参数 文件
常用参数:
    -V        grep版本号
    -E        可以使用扩展正则表达式,相当于使用egrep
    -F        只能匹配固定字符串,不能匹配到正则表达式
    -G        将范本样式视为普通的表示法使用,默认值
    -A num    匹配到搜索到的行以及该行下面的num行
    -B num    匹配到搜索到的行以及该行上面的num行
    -D num    匹配到搜索到的行以及上下各num行
    -v        取反
    -n        给grep过滤出来的内容加上行号
    -o        显示命令每一次匹配到了什么
    -i        不区分大小写
    -c        --count 计算符合样式的行数
 
    示例:
        准备文本
cat>translate.txt<<EOF
spring not boiling water 
herb not medical grass 
cable car not fly car 
mount Tai not Tailand
sunrise and sea of clouds not sun grow and skysea
fish and crabs not seafoods
pilgrimage not let your head duang duang duang on the ground
 
the Yangtze River not Long river
the Yellow River not Huang river
 
the Pearl River not Pig River
Flood not Lots of water
Ming dynasty not the kingdom of ming
Tang dynasty not Tang destiny
handicarft industry not people-making indstry
four great classical novels of Chinese literature not four big famous books
stable society not peace
'developed economy' not economic good
fleet not ship team 
emperor not yellow brother/China's boss
! = not
This isn't a pen.
Charles' brother
EOF
        练习
1. 过滤以m开头的行
    grep '^m' translate.txt
 
2. 过滤以r结尾的行
    grep 'r$' translate.txt
 
3. 不区分大小写,过滤出以m和s为开头的行
    grep -i '^[ms]' translate.txt
 
4. 过滤出文件中不是以m或f或e开始的行的反序
    grep -v '^[mfe]' translate.txt
    grep '^[^mfe]' translate.txt
 
5. 过滤出空行,并显示行号
    grep -n '^$' translate.txt
 
6. 统计每个字母出现的个数并按照个数升序排列
    grep -o '[a-Z]' translate.txt|sort|uniq -c|sort -n
 
7. 把文件中每个单词总共出现多少次统计出
    egrep -o "[a-Z]+'?[st]?" translate.txt|sort|uniq -c
 
 
        扩展:uniq,sort
uniq 参数 文件
    说明:用于报告或忽略文件中的重复行(连续的重复行)
    无    去除连续重复的多行
    -c    在每列旁边显示该行重复出现的次数
    -d    仅显示重复出现的行列
    -u    仅显示出现一次的行列
 
sort
    说明:对文件经行排序
    无    从首字母开始,按照0-9aAbB-zZ
    -b    忽略每行前面开始出的空格字符
    -c    检查文件是否已经按章顺排序
    -d    排序时,处理英文字母、数字及空格字符外,忽略其他的字符
    -f    排序时,将小写字母视为大写字母
    -n    依照数值的大小排序
    -r    反序
    -o    将排序后的结果存入指定的文件
    -t    指定排序所用的栏位分割字符,默认是空格
    -M    将前面3个字母按照月份的缩写进行排序
    -u    忽略相同行
    -k    自定义排序的字符,一般和-t使用
        FStart.CStart Modifier,FEnd.CEnd Modifier
        --------Start---------,------End--------
        说明:
            Modifier    上面的选项,一般不写,如r,n等
            FStart.Cstart 当用-t分割字符后,该式表示,从第几列字符串的第几个字符开始,
            FEnd.CEnd 该式表示,到达第几列字符串的第几个字符结束
            CStart 可以不写,默认为0
            CEnd 不写或设为0,则表示到该字符串的末尾
 
示例:
    1. sort -t ' ' -k 1.2 test.txt 
        # 说明:-t是按照空格拆分每行,然后按照第1个字符串的第2个字符到末尾排序
    2. sort -t ' ' -k 3,3 test.txt
        # 说明:按照第3个字符串排序,第二3可以省略
    3. sort -t ' ' -k 1.2,1.2 -k 3r text.txt
        # 说明:先按照第1个字符串的第2个字符排序,如果相等,按照第3个字符串的反序排序
 

3、sed

    SED(Stream EDitor) 是一项Linux指令,功能同awk类似,差别在于,sed简单,对列处理的功能要差一些
常用参数
    -V        --version    
    -h        --help
    -n        取消默认输出,与p结合使用
    -i        修改文件内容
    -i.bak    先备份,然后修改文件内容
    -r        支持扩展正则表达式
    ;         多条命令分隔符,取不连续的多行
    a         在某行后面追加一行内容
    i         在某行前面插入一行内容
    c         在原位置替换
    s         替换指定字符
    g         获得内存缓存区的内容,并代替当前模板块中文本
    p         表示打印行
    n         读取下一个输入行,用下一个命令处理新的行而不是用第一个命令
    d         删除,删除选择的行
    !         取反
    =         打印当前行号
 
    练习(文本使用上面的translate.txt)
===================================查
1. 取出第2行内容
    sed -n '2p' translate.txt
2. 取出第2到6行
    sed -n '2,6p' translate.txt
3. 取出第2,6行
    sed -n '2p;6p' translate.txt
4. 找到包含the的行
    sed -n '/the/p' translate.txt     # 双斜杠内是正则表达式
5. 显示从包含duang的行到包含the的行    
    sed -n '/duang/,/the/p' translate.txt
    # 说明:匹配第一个表达式的第一个结果,到匹配第二个表达式的第一个结果
6. 显示包含the的行和包含Ming的行
    sed -n '/the/p;/Ming/p' translate.txt
    sed -rn '/the|Ming/p' translate.txt
 
===================================增    # 不修改原文
1、在第2行后面追加一行内容“WuZhen not black town”
    sed '2a WuZhen not black town' translate.txt
    sed '3i WuZhen not black town' translate.txt
2. 在第2行追加多行内容“myth not god say”,”pioneer not first crazy”
    sed '2a myth not god say/npioneer not first crazy' translate.txt
    sed '3i myth not god say/npioneer not first crazy' translate.txt
3. 在末尾添加一行“express package not my taobaos”
    sed '$a express package not my taobaos' translate.txt
 
===================================删
1. 删除第3行
    sed '3d' translate.txt
2. 删除第2到6行
    sed '2,6d' translate.txt
3. 删除第2行和第6行
    sed '2d;6d' translate.txt
4. 删除空行
    sed '/^$/d' translate.txt
5. 删除空行,但有的空行里有空格和tab键
    sed -r '/^[ \t\n\r]*$/d' translate.txt
6. 删除文件以the开头的行
    sed '/^the/d' translate.txt
 
===================================改
1. 把文件的单词the都修改成 THE    # g全局(一行)替换,也可以ng,n表示从第n个字符开始
    sed -r 's#the\b#THE#g' translate.txt    #\b表示以单词的边界查找单词
2. 把以the开头的行都换成 'abcdefg'
    sed -r 's#^the.*$#abcdefg#g' translate.txt
3. 通过ifconfig 查出本机的ip地址
    ifconfig eth0|sed -nr "2s# *inet (.*?)( n.*)#\1#gp"    #\1表示第一个分组的结果
    ifconfig eth0|sed -n '2p'|sed -r 's#(.*t )(.*)(  n.*$)#\2#g'
 
 
       特殊操作
特殊操作:
&: 表示之前匹配到的结果
    在所有的127.0.0.1后面添加localhost
       sed 's/127.0.0.1/&localhost/g' test.txt    # 斜杆和#表达的含义一样,都是分割符
 
 
{}: 表示一条匹配的结果可以执行多次操作
    找到含有the行的下一行,把字母全变成大写
        sed '/the/{n; s/.*/\U&/g}' translate.txt    # {}可以放多个操作
强调
    {} 和 -e的区别:都可以表示执行多个操作;
    -e 表示第一个执行完后再执行第二个,
    {} 表示满足当前条件的一条数据操作完后,再操作下一条数据
    如:sed -e '1,12d' -e 's/the/THE/g' translate.txt    # 表示先删除1到12行,再修改
 
q:退出指令
    打印完第3行退出:sed '3q' translate.txt
 
打印奇数行或偶数行
    sed -n '{p;n}' translate.txt  #奇数行
    sed -n '{n;p}' translate.txt  #偶数行

4、awk

    AWK 是一种用于处理文本的编程语言工具, AWK 提供了极其强大的功能:可以进行样式装入、流程控制、数学运算符、进程控制云居甚至于内置的变量和函数。
    语法:awk '{pattern+action}' 或者 awk 'pattern {action}'
    常用参数
    -V               版本信息
    NR               表示行号,用法NR==2,表示取第2行
    $n               取某一列的内容
    $0               取一整行内容
    $NF              最后一列
    -v               赋值一个用户定义变量,将外部变量传递给awk
    FS               简写F输入域分隔符,默认是一个空格
    OFS              输出域分隔符,默认是一个空格
    !                非
    i=i+1            计算次数,总和
    i=i+某一列        计算总和,累加
 
    准备文本
cat >>reg.txt<<EOF
Zhang Dandan    41117397   :250:100:175
Zhang Xiaoyu    390320151  :155:90:201
Meng  Feixue    80042789   :250:60:50
Wu    Waiwai    70271111   :250:80:75
Liu   Bingbing  41117483   :250:100:175
Wang  Xiaoai    3515064655 :50:95:135
Zi    Gege      1986787350 :250:168:200
Li    Youjiu    918391635  :175:75:300
Lao   Nanhai    918391635  :250:100:175
EOF
    练习
1. 取出第三列以4开头的行
    awk '$3~/^4/{print $0}' reg.txt
    awk '$3~/^4/' reg.txt
    # 说明:
    #     $3 第3列;
    #     ~:匹配正则表达式,!~表示取反
    #     //:中间是正则表达式
    #     {}: 每一次要处理一行时,要采取的操作
 
2. 姓氏为zhang 的人,显示他的第二次捐款
    awk -F '[ :]+' '/Zhang/{print $1,$2,$(NF-1)}' reg.txt
 
3. 显示第三列所有ID号码最后一位数字是1或5的人的全名
    awk -F "[ ]+" '$3~/[15]$/{print $1,$2}' reg.txt
    awk -F "[ ]+" '$3~/1$|5$/{print $1,$2}' reg.txt
 
4. 显示Xiaoyu的捐款.每个值时都有以$开头.如$520$200$135
    awk '/Xiaoyu/{print $4}' reg.txt |sed 's#:#$#g'
    awk '/Xiaoyu/{print $4}' reg.txt |tr ':' '$'
    awk -F '[ :]+' -vOFS='$' '/Xiaoyu/{print "$"$4,$5,$6}' reg.txt
    awk -F '[ :]+' '/Xiaoyu/{print "$"$4"$"$5"$"$6}' reg.txt
 
5. 使用ifconfig取IP地址
    ifconfig eth0|awk 'NR==2{print $2}'
 
6. 统计/etc/services文件中的空行的数量    
    grep '^$' /etc/services |wc -l      
    sed  -n '/^$/p' /etc/services |wc -l
    awk  '/^$/{i=i+1}END{print i}' /etc/services
 
7. 求文件内100以内的和
    seq 100 > num.txt
    awk '{i=i+$1}END{print i}' num.txt
 
扩展
    wc用来计算数字,
        -b     bytes数
        -l     lines行数
        -w     words字数
 
    seq 产生从某个数到另外一个数之间的所有的整数
        seq [选项] 尾数
        seq [选项] 首数 尾数
        seq [选项] 首数 增量 尾数
        -f    format,指定打印的格式
        -w    在列前添加0,使得宽度相同(不能和-f一同使用)
        -s    使用指定字符串分割数字(默认'\n')
    如:
        seq -s ' ' -f 'str%03g' 1 3
        str001 str002 str003
    说明tr%03g:
        默认%g,%前面是自定义得字符串
        %后面03表示,数字位数不足3位补0,默认补空格
            
 
    对日志操作
从本机到虚拟机CentOS7文件传输方式
1. 使用scp,前提是本机能通过ssh连接到虚拟机内ssh root@10.0.0.100,
    在本机上输入以下命令:(如果是多个文件夹 使用-r)
    scp local_file 用户名@ip:文件夹路径
    scp  /Desktop/secure  root@10.211.55.8:/tmp/
    scp  /Desktop/access.log  root@10.211.55.8:/tmp/
  
2. 使用rz,仅限windows
    yum install -y lrzsz
        rz 上传
        sz 下载
 
    练习
access.log第一列是IP地址 第七列是访问的路径,第十列是服务端响应给客户端的字节数
1. 统计access.log的服务端响应给客户端的总字节数
    awk '{i=i+$10}END{print i}' access.log
 
2. 统计access.log的每个访问ip出现的次数最多的十个
    awk '{print $1}' access.log |sort|uniq -c|sort -nr|head -10
    awk '{i[$1]+=1}END{for (ip in i) print ip, i[ip]}' access.log |sort -nrk 2|head -10  # i[$1]+=1建立一个字典,key为第一个只,key的个数为value
 
3. 统计access.log中被请求最多的路径
    awk '{i[$7]++}END{for(path in i) print i[path], path}' access.log |sort -nr|head -1
 
4. 统计access.log中每个ip地址的访问次数和每个ip地址服务端响应的总字节数
    awk '{i[$1]++;j[$1]+=$10}END{for(ip in i) print ip, i[ip],j[ip]}' access.log
 
5. 统计secure日志中,谁在破解你的密码(每个破解你密码的ip的出现次数的前十个)
    awk '/Failed password/{i[$(NF-3)]++}END{for(ip in i)print ip,i[ip]}' secure |sort -nrk 2| head -10|column -t
 
说明:
    column -t:表示列的格式化输出
 
 
posted @ 2019-06-20 13:41  yw_sun  阅读(1106)  评论(0编辑  收藏  举报