• 常用文本处理命令


    Linux中很多文本工具都使用到了正则表达式,正则表达式可以极大的简化linux系统管理工作,因为网上有很多正则相关的教程,所以这里不再讲述,我当时看的是菜鸟的正则表达式,看个一下午在实验几遍基本就会了,除了正向肯定预查,反向肯定预查这几个比较复杂一些,其他都是非常简单的,很多时候记不住也可以查询网上对着写,并不需要你实时记住。这里主要谈谈awk等用到正则表达式的文本处理工具。

    一、awk

    awk的指令必须包含在单引号中。

    基本句式

    awk -F'指定输入分隔符' 'BEGIN{做一些初始化工作} 一些过滤条件 {针对每行的工作}... END{最后收尾工作}'

    中间的处理块可以有多个,通过过滤条件单每行都会走一遍过滤条件,其中BEGIN和END边只会执行一遍

    过滤记录

    1. awk '$30 && $6"LISTEN" ' netstat.txt
    2. awk '$30 && $6"LISTEN" || NR==1 ' netstat.txt

    指定分隔符

    1. awk -F: '{print $1,$3,$6}' /etc/passwd等价于awk 'BEGIN{FS=":"} {print $1,$3,$6}' /etc/passwd
    2. awk -F '[;:]' 指定多个分隔符
    3. awk -F: '{print $1,$3,$6}' OFS=" " /etc/passwd指定输出分隔符

    需要注意的是上面print $1,$3,$6中的,被替换成了分隔符,如果是print $1$3$6则中间没有分隔符

    特殊关键字:

    1. NR 目前处理的行号
    2. NF 当前处理的行一共用到的字段数目
    3. FNR 目前处理的文件的行号(当处理多个文件时,NR会不停的累加,但如果是FNR则在处理新文件是从1开始)
    4. FILENAME 文件名
    5. $0 当前整行
    6. FS 输入字段分隔符 默认是空格或Tab
    7. RS 输入记录分隔符 默认为换行符
    8. OFS 输出字段分隔符 默认是空格或Tab
    9. ORS 输出记录分隔符 默认为换行符

    正则

    1. 普通匹配: awk'/hello/ {print}' test.sh
    2. 匹配取反: awk '!/hello/ {print}' test.sh
    3. 同时匹配: awk '/hello/ && /world/ {print}' test.sh
    4. 或者匹配: awk '/hello/ || /world/ {print}' test.sh 也可以写成awk '/hello|world/ {print}' test.sh
    5. 指定列匹配: awk '$5 ~ /hello/ {print}' test.sh
    6. 指定列匹配取反: awk '$5 !~ /hello/ {print}' test.sh

    输出到不同的文件

    1. $ awk 'NR!=1{if($6 ~ /TIME|ESTABLISHED/) print > "1.txt"; else if($6 ~ /LISTEN/) print > "2.txt"; else print > "3.txt" }' netstat.txt
    2. awk 'NR!=1{print > $6}' netstat.txt

    其实使用了 >重定向,上例子使用了if语句

    1. 统计数据: awk 'NR!=1{a[$6]++;} END {for (i in a) print i ", " a[i];}' netstat.txt
    2. 行数筛选,开头和结尾的条件使用,分隔: awk '/test1/,/test2/ {print}' test.txt

    和环境变量的交互

    $ x=5
     
    $ y=10
    $ export y
     
    $ echo $x $y
    5 10
    $ awk -v val=$x '{print $1, $2, $3, $4+val, $5+ENVIRON["y"]}' OFS="	" score.txt
    Marry   2143    78      89      87
    Jack    2321    66      83      55
    Tom     2122    48      82      81
    Mike    2537    87      102     105
    Bob     2415    40      62      72
    

    二、grep

    参数列表:

    1. -w 匹配整个单词
    2. -s 忽略文件不存在等报错
    3. -l 仅列出匹配文件列表
    4. -L 仅列出不匹配文件列表
    5. -A 显示后的行数 如-1 匹配行的后1行
    6. -B 显示前的行数 如-1 匹配行的前1行
    7. -number 显示前后的行数 如-1 匹配行的前后1行
    8. -n 打印行数
    9. -c 仅显示个数
    10. -v 反向
    11. -o 仅显示匹配的内容
    12. -E 则表示要使用EREs
    13. -P 则表示要使用PREs

    grep主要就是一个正则表达式的使用,其中需要注意正则有三种BREs、EREs和PREs。前两种不支持非贪婪匹配。grep默认是BREs,所以他?,+,|,{,},(,)
    这种字符都需要用转义,另外他不支持s,S,D,d, 等字符。

    三、sed

    sed命令在自动化脚本编写的过程还是经常用到的。

    基本句式: sed -nfei [操作]

    操作: n1,n2 动作

    动作:

    1. d: 删除
    2. s: 替换,行内替换,行内匹配的字符串,如hello world该行替换hello为hi变成hi world
    3. a和i: a增加在匹配的后面增加行 i增加在匹配的前面增加行
    4. c :替换,针对整行替换

    例子:

    1. sed -e 's/hello/hi/g':替换文本,-e可以省略
    2. sed -e '1,2s/hello/hi/g' -e '3,4s/world/man/g:等价于sed -e '1,2s/hello/hi/g;3,4s/world/man/g
    3. sed s/hello (world)/1 hi/g':群组匹配,可以使用 选择前面的群组

    四、sort和uniq

    sort参数

    1. -r: 默认升序,-r表示反序
    2. -u: 移除重复
    3. -o: 重定向到文件,注意sort test.txt >test.txt 不可用,因为> 是想清空文件,所以会导致文件在排序之前就清空了
    4. -n: 默认按字符排序,如10小于2,-n表示按数字排序
    5. -t: 指定分隔符
    6. -k: 指明用哪一列来做排序
    7. -b: 忽略每行前面开始出的空格字符

    例子:

    1. sort -t $' ' -k 1 -u res.txt > res2.txt 以tab作为分隔符,按第一列排序并去重

    uniq参数

    需要注意uniq需要文本是有序的,所以一般使用uniq的时候是用更早sort的管道后面

    1. -c:显示出现的次数
    2. -d:仅显示重复出现行;    
    3. -u :仅显示出一次的行列;   

    说说sort|uniqsort -u,一直觉得很奇怪,两者有什么区别,功能是一样的。sort -u是后面加入的,所以很多人还是使用了sort|uniq
    目前推荐使用sort -u,因为还少了进程间通讯。

    五、实战

    处理以下文件内容,将域名取出并进行计数排序,如处理:

    http://www.baidu.com/index.html
    http: / / www.baidu.com/1.html
    http://post.baidu.com/index.html
    http://mp3.baidu.com/index.html
    http://www.baidu.com/3.html
    http://post.baidu.com/2.html
    得到如下结果:
    3 www.baidu.com
    2 post.baidu.com
    1 mp3.baidu.com

    解法1:grep -Po '(?<=//)(.*?)(?=/)' test.txt |sort |uniq -c|sort -nr

    1.利用了Perl,他支持非贪婪,2.利用了正向和反向预查(正向预查是后面的(?=)) 3.利用了-o参数只输出匹配的内容

    解法2:awk -F/ '{print $3}' test.txt |sort |uniq -c|sort -nr

    指明了分割符号 直接取对应值

    解法3:sed 's/http://([^/]*).*/1/' test.txt|sort |uniq -c|sort -nr

    基本的正则中小括号需要转义,如果采用-r参数即扩展的正则小括号不用转义

    解法4: sed -e 's/http:////' -e 's//.*//' | sort | uniq -c | sort -rn

    采用了替换,先替换前面的,在替换后面的

    awk例子

    需要注意awk不支持多维数组,采用了一种变通的方式,普通的使用没问题,但是如果需要存的值是一个map就不合适了,如下
    文件 1-6列分别为deal od sum up lj day ,现在要计算sum up lj day 的累加和输出
    输出也要是deal od sum up lj day也就是sum up lj day需要是一个map,不过awk做不到这点

    {
        updealids:{
            od: {day,sum,up,lj}
            
        }
    }
    awk 'BEGIN{OFS="	"}{result[$1,$3,"sum"]+=$4;result[$1,$3,"up"]+=$5;result[$1,$3,"lj"]+=$6;result[$1,$3,"day"]=$2}
    END{for ( i in result)   {split(i, a, SUBSEP); print result[i] ,a[1], a[2], a[3] }}'  *
    

    参考资料:

    1. AWK 简明教程
    2. SED 简明教程
  • 相关阅读:
    GlusterFS安装部署
    glusterfs peer失败
    GlusterFs 启动报错
    利用idea反编译jar包
    hive 错误记录 之moveing 失败
    节点不可用,显示noReady
    kafka 配置认证与授权
    flink (2) 读取kafka数据
    Flink (1) 安装部署
    redis the cluster is down
  • 原文地址:https://www.cnblogs.com/chenfangzhi/p/11997028.html
Copyright © 2020-2023  润新知