• Linux 文本处理三剑客


    一、grep:文本过滤工具

    grep 语法格式:

    grep [OPTIONS] PATTERN   [FIFE]
    grep   参数     匹配模式  查找的文件
    
    参数选项 解释说明
    -v 显示不匹配的行,或者说排除某些行,显示不包含匹配文本的所有行
    -n 显示匹配行及行号
    -i 不区分大小写(只适用于单字符),默认是区分大小写的
    -c 只统计匹配的行数,注意不是匹配的次数
    -E 使用扩展的 egrep 命令
    --color=auto 为 grep 过滤的匹配字符串添加颜色
    -w 只匹配过滤的单词,单词的两边必须是非字符符号(即不能是字母数字或下划线)
    -o 只输出匹配的内容

    有文本如下(test.txt)

    test
    dongye
    oldboy
    
    linux
    ubuntu
    centos
    
    LOL
    dota2
    i like playing dota2
    

    1.1 -v 参数实践

    # 过滤不包含oldboy字符串的行,注意被过滤的字符串,尽可能使用双引号
    grep -v "dota2" test.txt
    
    >>>
    test
    dongye
    oldboy
    
    linux
    ubuntu
    centos
    
    LOL
    

    提示: grep 的 -v 参数的作用是排除,默认是以行为单位排除包含参数后面所接内容的某些行

    1.2 -n 参数实践

    # 输出包含 oldboy 字符串的行,并显示行号
    grep -n "dota2" test.txt
    
    >>>
    1:dota2
    2:i like playing dota2
    

    提示: -n 参数会对 grep 命令找到的内容在开头加上对应的行号

    1.3 -i 不区分大小写参数实践

    grep "lol" test.txt
    
    >>>
    找不到值
    grep -i "lol" test.txt
    >>>
    LOL
    

    1.4 -E 和 --color 的参数实践

    # 默认不支持多条件匹配
    grep "like|dota2" test.txt
    
    # 多条件匹配,加 -E
    grep -E "like|dota2" test.txt   
    
    >>>
    dota2
    i like playing dota2
    
    # 加颜色
    grep -Ei --color=auto "like|dota2" test.txt
    

    1.5 -c 参数实践

    grep "dota2" test.txt
    
    >>>
    dota2
    i like playing dota2
    
    # 只想计算匹配的字符串的数量
    grep -c "dota2" test.txt
    
    >>>
    2
    

    1.6 -o 参数实践

    # 注意这里没有 双引号
    grep -o dota2 test.txt
    
    >>>
    dota2
    dota2
    

    1.7 -w 参数实践

    grep -w "like" text.txt
    
    # 结果为空
    

    1.8 grep 常用

    # 查找指定进程
    ps -ef | grep nginx
    
    # 查找指定进程并统计数量
    ps -ef | grep -c nginx
    
    # 从文件中查找关键字
    grep 关键字 test.txt
    
    # 从文件中查找关键字并输出它的行号
    grep -n 关键字 text.txt
    
    # 从多个文件中查找关键字
    grep 关键字 test1.txt test2.txt test3.txt
    
    # 从文件中查找关键字后,再从结果中找到指定关键字
    cat text.txt | grep -v 不要的关键字 | grep -w 要的单词
    ps -ef | grep dub-finance | grep -v grep | awk '{print $2}' | xargs kill -9
    
    # 找出文件中的空白行
    grep -n "^$" test.txt
    
    # 显示当前目录下面以 .txt 结尾的文件中的所有包含每个字符串至少有4个连续小写字符的字符串的行
    grep -n '[a-z]{4}' *.txt
    

    二、sed:字符流编辑器

    语法格式

    sed [选项] [sed内置命令字符] [输入文件]
    

    说明:

    1. sed以及后面的选项、命令和输入文件,每个元素之间都至少要有一个空格。
    2. 【sed内置命令字符】,既可以是单个命令,也可以是多个命令参数的组合
    3. 【输入文件】为sed 需要处理的文件,这是可选项,sed 还能够从标准输入如管道中获取输入

    2.1 选项、内置命令说明

    参数选项

    参数选项 解释说明
    -n 取消默认的sed的输出,常与sed内置命令的p连用
    -i 直接修改文件内容,而不是输出到终端。如果不使用 -i 选项,则sed只是修改内存中的数据,并不会影响磁盘上的文件

    sed内置命令字符

    sed的内置命令字符 解释说明
    a 全拼 append,表示追加文本,在指定行后添加一行或多行文本
    d 全拼 delete,表示删除匹配行的文本
    i 全拼 insert,表示插入文本,在指定行前添加一行或多行文本
    p 全拼 print,表示打印匹配行的内容,通常 p 会与选项 -n 一起使用
    s/regexp/replacement 匹配 regexp 部分的内容,用 replacement 替换 regexp 匹配的内容,regexp部分可以使用正则表达式,在 replacement 部分可以使用特殊字符 & 和 1-9等匹配 regexp 部分的部分内容。在实战场景中,s/regexp/replacement/g 结尾常与g匹配做全局的替换

    2.2 示例文本

    先准备一个文本 tex.txt

    101,oldboy,CEO
    102,zhangyao,CTO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CTO
    

    2.3 在文本指定行后追加文本

    sed "2a 106,dandan,CSO" test.txt
    
    >>>
    101,oldboy,CEO
    102,zhangyao,CTO
    106,dandan,CSO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CTO
    

    2a 106,dandan,CSO的意思:

    1. 2 表示对第 2 行进行操作,其他的行忽略
    2. a 表示追加,2a 即在第 2 行后追加文本
    3. 2a 后面加上空格,然后接着输入想要追加的文本内容(106,dandan,CSO`)即可

    2.4 在文本指定的行前面插入文本

    sed "2i 106,dandan,CSO" text.txt
    
    >>>
    101,oldboy,CEO
    106,dandan,CSO
    102,zhangyao,CTO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CTO
    

    2i 106,dandan,CSO的意思:

    1. 2 表示对第 2 行进行操作,其他的行可忽略
    2. i 代表插入的意思,2i 表示在第2行即当前行插入文本,即插入到第二行
    3. 2i 后面加上空格,然后跟上要插入的文本(106,dandan,CSO),最后接上要处理的文件 text.txt

    2.5 在文件指定行后追加多行文本

    sed "2a 106,dandan,CSO
    107,bingbing,CCO" text.txt
    
    >>>
    101,oldboy,CEO
    102,zhangyao,CTO
    106,dandan,CSO
    107,bingbing,CCO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CTO
    

    2.6 删除文件中一行指定的文本

    sed "2d" text.txt
    
    >>>
    101,oldboy,CEO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CTO
    

    2.7 删除文件中指定的多行文本

    sed "2,5d" text.txt
    # 表示删除 2-5 行,所以结果只剩下一行
    >>>
    101,oldboy,CEO
    

    2.8 使用sed命令替换文本内容

    sed "s#zhangyao#dandan#g" text.txt
    
    >>>
    101,oldboy,CEO
    102,dandan,CTO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CTO
    

    2.9 打印输出文件的指定行的内容

    sed "2p" text.txt
    
    # 这里使用了 sed 内置命令 p 来实现查询功能,并结合数字地址指定查询第2行的内容,但是我们会发现结果不只是输出第2行,文件的其他内容也显示出来了,这是因为 sed 命令有一个默认输出的功能.
    >>>
    101,oldboy,CEO
    102,zhangyao,CTO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CTO
    
    
    sed -n "2p" text.txt
    
    # 为了解决上面命令显示多余内容的问题,使用选项 -n 取消默认输出,只输出匹配行的文本,因此大家只需要记住使用命令 p 必用选项 -n
    >>>
    102,zhangyao,CTO
    
    
    sed -n "2,4p" text.txt
    # 输出 2-4 行
    >>>
    102,zhangyao,CTO
    103,Alex,COO
    104,yy,CFO
    

    2.10 -i 选项

    	这个选项的作用是能够实际修改文件的内容,前面几个例子操作完命令之后,文件的内容并没有发生变化,这是因为 sed 命令默认操作的是内存中的数据,如果想要真正地修改文件的内容,就需要使用选项 `-i`将修改写到磁盘文件上。
    

    2.11 N 内置命令

    有文件如下

    stu10309
    7f754wdw
    stu10123
    faioj322
    stu12452
    fasdassa
    ...
    

    现在要把格式变成

    stu10309=7f754wdw
    stu10123=faioj322
    stu12452=fasdassa
    

    可用以下方法实现

    sed "N;s#
    #=#g" text.txt
    
    	sed 内置命令 N 的作用:不会清空模式空间的内容,并且从输入文件中读取下一行数据,追加到模式空间中,两行数据以换行符 
     连接。
    
    	第一行是 `stu10309` 存入模式控件,碰到命令 `N`,读取第二行 `7f754wdw`,此时模式空间的内容为 `stu10309
    7f754wdw`;然后执行 `s#
    #=#g` 将 `
    `替换为 `=`,即为 `stu10312=`7f754wdw`,输出到屏幕中,第一个循环结束;后面的循环和前面的思路一样,直到文件结束。
    

    三、awk 基础入门

    	不仅是Linux系统中的一个命令,而且还是一种编程语言。是Linux系统最强大的文本处理工具,没有之一。
    

    3.1 参数选项及说明

    awk 命令的常用功能 简要例子说明
    指定分隔符显示某几列 awk -F "GET|HTTP" '{print $2}' test.log 直接取出显示出日志文件的 url 这一列
    通过正则表达式取出你想要的的内容 awk '$6~/Failed/{print $11}' /var/log/secure 分析生产环境中的日志找出谁在破解用户的密码
    显示出某个范围内的内容 awk 'NR20,NR30' filename 显示文件的20到30行内容
    通过awk进行统计计算 awk '{sum+=$0}END{print sum}' ett.txt 计算总和
    awk数组计算与去重 awk '{array[$1]++}END{for(key in array)print key,array[key]}' access.log 对日志进行统计与计数
    awk  [option]  'pattern{action}' file ...
           参数         '条件{动作}'    文件 ... 
    

    参数选项及说明

    参数选项 解释说明
    -F 指定字段分隔符
    -v 定义或修改一个 awk 内部的变量

    3.2 示例文本

    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/mologin
    adm:x:3:4:adm:/var/adm:/sbin/lologin
    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    sync:x:5:0:sync:/sbin:/bin/sync
    shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
    halt:x:7:0:halt:/sbin:/sbin/halt
    mail:x:8:12:mail:/var/spool?mail:/sbin/nologin
    uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
    

    3.3 显示文件中的第5行

    cat -n test.txt   # 先打印内容并在每行内容的开头显示行号
    
    awk 'NR==5' test.txt
    
    	首先NR 在awk中表示行号(记录号),NR==5表示行号等于5的行。这里需要注意的是必须使用两个等号,在awk中两个等号表示 ”等于“,一个等号表示赋值,即向一个变量里面放置内容。
    

    注意:awk后面所接的内容要用单引号

    显示一部分行的内容,例如显示 2-6 行

    awk 'NR==2,NR==6' test.txt
    

    3.4 用 awk 实现给文件每行的内容之前加上行号

    awk '{print NR,$0}' test.txt
    

    这里的NR还是表示行号,$0 表示一整行的内容(一行的内容)。

    3.5 显示第 2 行到 第 6 行,并打印行号

    awk 'NR==2,NR==6 {print NR,$0}' test.txt
    

    3.6 显示文件的第 1 列、第 3 列和最后一列

    awk -F ":" '{print $1,$3,$NF}' test.txt
    
    	这里我们使用了 awk 的 -F参数。-F表示指定一个`分隔符`来切割每一行的内容,-F后面可用单双引号或不加引号,但是,建议加双引号。
    
    	`$1`表示根据分隔符分割的第一列,`$2`表示根据分隔符分割的第二列,以此类推。
    
    	`$0`表示整行。`$NF`表示最后一列。
    

    3.7 把文件中的 /sbin/nologin 替换为 /bin/bash

    awk '{gsub("/sbin/nologin","/bin/bash",$0);print $0}' test.txt
    

    3.8 生产案例1:取出 eh0 网卡对应的ip地址

    ifconfig eth0
    
    >>>
    eho Link encap:Ethernet Hwaddr 00:0C:29:93:49:99
    inet addr:10.0.0.8 Bcast:10.0.0.255 Mask:255.255.255.0
    ...
    

    ​ 取出的方式

    ifconfig eth0|awk -F "(addr:)|(  Bcast:)" 'NR==2{print $2}'
    >>>
    10.0.0.8
    

    ​ 我们的目标是取得ip,本例是10.0.0.8,ip的左边是 addr:,右边是 Bcast:。所以两边都是分隔符,就可以取到我们想要取到的值。(这里需要注意-F 指定多分割符的写法

    ​ 还有一个简单的方法

    ifconfig eth0|awk -F "[ :]+" 'NR==2{print $4}'
    

    ​ 结合起来,-F "[ :]+"就是以单个或连续的空格或冒号或者它们的组合为分隔符。最后就可以获得我们想要的ip地址。

    3.9 面试题--统计域名访问次数

    测试数据如下:

    http://www.etiantian.org/index.html
    http://www.etiantian.org/1.html
    http://post.etiantian.org/index.html
    http://mp3.etiantian.org/index.html
    http://www.etiantian.org/3.html
    http://post.etiantian.org/2.html
    

    3.9.1 方案1

    (1)取出每行中的域名

    awk -F '/' '{print $3}' test.txt
    
    >>>
    www.etiantian.org
    www.etiantian.org
    post.etiantian.org
    mp3.etiantian.org
    www.etiantian.org
    post.etiantian.org
    

    (2)排序(让相同的域名相邻)

    awk -F '/' '{print $3}' test.txt|sort
    

    (3)去重计数

    awk -F '/' '{print $3}' test.txt|sort|uniq -c
    

    3.9.2 方案2(awk数组方案)

    (1)取出域名

    awk -F '/' '{print $3}' test.txt
    

    (2)创建一个 awk 数组,然后把第二列(域名)作为数组的下标,再通过类似于 i++ 的形式来计算域名重复的次数

    awk -F '/' '{hotel[$3]}' test.txt  # 创建 awk 的hotel 数组
    awk -F '/' '{hotel[$3];print $3}' test.txt  #创建 awk 的hotel 数组,并通过 print 输出元素名字(房间号码),注意,这里没输出数组,所以看到的还是第一阶段的内容
    
    >>>
    awk -F '/' '{print $3}' test.txt
    

    (3)开始统计

    awk -F '/' '{hotel[$3]++;print $3,hotel[$3]}' test.txt
    
    >>>
    www.etiantian.org 1
    www.etiantian.org 2
    post.etiantian.org 1
    mp3.etiantian.org 1
    www.etiantian.org 3
    post.etiantian.org 2
    

    (4)输出最终结果

    上面的命令详细地显示了 awk 统计的过程。如果想要获得最终结果该怎么办呢?通过END模式来输出最终结果。

    awk -F '/' '{array[$3]++}END{
    print "www.etiantain.org",array["www.etiantian.org"];
    print "post.etiantian.org",array["post.etiantian.org"];
    print "mp3.etiantian.org",array["mp3.etiantian.org"];
    }' test.txt
    

    awk数组提供了自己独有的方法来完成它——一个专用的循环:

    awk -F '/' '{hotel[$3]++}END{for(domain in hotel)print damain,hotel[domain]}' test.txt
    
    >>>
    mp3.etiantian.org 1
    post.etiantian.org 2
    www.etiantian.org 3
    
    
  • 相关阅读:
    几个.net开源项目(转)
    UILabel显示换行的方法
    使用TDBXReader或TDataSet回传数据,中文乱码问题解决办法
    NSDateFormatter setDateFormat 自定义日期时间格式
    iPhone开发之打包zip文件
    创建log文件的代码
    去除iphone图标的半弧高亮效果
    Ajax XMLHttpRequest对象open方法的参数 为什么要把时间戳追加到目标URL?
    时间校验
    WPF视频
  • 原文地址:https://www.cnblogs.com/dongye95/p/14450235.html
Copyright © 2020-2023  润新知