0%

Linux文本处理三剑客

有的花开得比较早,有的花开得比较晚,但都有绽放的那一天。人也是一样,每个人都有属于自己的节奏,在自己的节奏上走好,便是最好!

一、grep:文本搜集工具

  1. grep,全称Globally search a Regular Expression and Print,是一种强大的文本搜索工具,它能使用特定模式匹配(包括正则表达式)搜索文本,并默认输出匹配行。

  2. 语法,grep --help可查看完整参数,简写为grep [选项] "模式" [文件]

  3. demo

    • 查看php进程
    • 包含grep搜索文本ps -ef | grep php
    • 不包含grep搜索文本ps -ef | grep php | grep -v 'grep'
    • 除123.txt外删除其余所有文件rm -rf $(ls | grep -v "123.txt")

grep -C/-A/-B

二、sed:以行为单位的文本编辑工具

  1. sed是一种流编编器,它是文本处理中非常中的工具,能够完美的配合正则表达式便用,功物能不同凡响。处理时,把当前处理的行存储在临时缓冲区中,称为”模式空间”(oattern space),接看用sed命令处理缓冲区中的内容,处理成后,把缓冲区的内容送往屏幕显示。接着理下一行,这样不断重复,直到文件末。文件内容没有改改变,除非使用了写入的命令,将内容更新。

    • 执行时sed会从文件或者标准输入中读取一行,将其复制到缓冲区,对文本编辑完成之后,读取下一行直到所有的文本行都编辑完毕。sed命令处理时只会改变缓冲区中文本的副本,如果想要直接编辑原文件,可以使用-i选项或者将结果重定向到新的文件中。
  2. 语法sed [-hnV][-e<script>][-f<script文件>][文本文件]

    • sed [options] commands [inputfile],sed执行时会从文件或者标准输入中读取一行,将其复制到缓冲区,对文本编辑完成之后默认输出到屏幕,读取下一行直到所有的文本行都编辑完毕。
      • 常见options参数
        • -n:取消默认输出(默认每一行都会输出),可通过sed 'p' sec.txtsed -n 'p' sed.txt对比理解
        • -e:多点编辑(可以执行多个子命令),一般用法为sed -e command1 -e command2
        • -f:从脚本文件中读取命令(sed操作可以事先写入脚本,然后通过-f读取并执行),适用于编写大量shell脚本时场景
        • -i:直接编辑原文件(dangerous)
        • -l:指定行的长度
        • -r:在脚本中使用扩展表达式
  3. demo

    • sed -n '1~2 p' 123.txt,表示从第一行开始,行号递增2输出,即输出奇数行。

    • 准备工作

      • 初始化数据脚本init_data.sh
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      #!/bin/bash
      list=(tom jerry jack jhon)
      list[4]=mike

      len=${ #list[*]}

      for((i=0;i<($len);i++))
      do
      echo ${list[$i]} >> sed.txt
      done
      • cat sed.txt
      1
      2
      3
      4
      5
      tom
      jerry
      jack
      jhon
      mike
      • 默认输出:sed '1,3 p' sed.txt

        • 使用p子命令输出缓冲区内容,'1 p'代表打印第一行,’1,3 p’代表打印1到3行,’1,$ p’则是打印全部(可简写为'p')。
        1
        2
        3
        4
        5
        6
        7
        8
        tom
        tom
        jerry
        jerry
        jack
        jack
        jhon
        mike
      • 取消默认输出:sed -n '1,3 p' sed.txt

        • 不使用-nsed首先读取一行,并默认将缓冲区内的文本输出出来,之后p子命令再次输出;使用-n时默认输出取消,只输出p子命令的结果。
      1
      2
      3
      tom
      jerry
      jack
      • 插入文本(a是在指定行下一行写入,i则是指定行前写入,两者用法基本一致,只做a演示)
        • Mac下sed -i需要带一个字符串作为备份源文件的文件名称,如sed -i "bak_filename" "s/'//g" a.txt
        • sed '2 a xxx' sed.txt,只在执行时显示一下,如果要写入文件则加-i选项
          • Mac下不太一样(注意a\后有空格),xxx回车另起一行或者写入文件再执行
         
1
2
3
4
5
6
7
8
sed '2 a\  
xxx
' sed.txt

#!/bin/bash
sed '2 a\
xxx
' ./sed.txt
1
2
3
4
5
tom
jerry
xxx
jack
jhon
* 执行多个命令`-e` * `sed -n -e '1 i command_i' -e '1 a command_a' -e '1,$ p' sed.txt` * `sed -n -e '1 i command_i' -e '1 a command_a'` * 从文件中读取执行`-f` * 1.sh
1
1,$ p
* 执行:`sed -f 1.sh sed.txt` * 直接替换`-i` * `sed -i -e '1 i command_i' -e '1 a command_a' sed.txt` * 替换命令`sed s/pattern/replacement/flags` * flags * 默认只替换第一个匹配到的字符 * 数字则表示将替换掉第几处被匹配到的数据 * `g`表示替换所有匹配到的数据 * `p`表示会打印出被匹配出来的行 * `w`标识将匹配替换后输出保存到指定文件`sed 's/tom/lin/gw out.txt' sed.txt` * `sed.txt文件`
1
2
3
4
5
6
7
8
9
command_i
tom little tom old tom
command_a
jerry
xxx
jack
jhon
another tom
+++
* 正则匹配 * 2.txt文本内容如下
1
2
3
4
5
6
*123123
222
333
444
555
666
* 删除不以`*`开头的文本,替换`*`:`sed -e '/^[^*]/d' -e 's/\*\(\d*\)/\1/' 2.txt`
  • a.txt

    1
    2
    3
    4
    1,2,3
    4,5,6
    7,8,9
    a,b,c
    • 行首加单引号:echo abc | sed "s/^/'/g"
    • 行尾加单引号:echo abc | sed "s/$/'/g"
    • 在行首行尾加引号sed "s/.*/'&'/g" a.txt
      • 写入:sed -i ".bak" "s/.*/'&'/g" a.txt
      • 写回:sed -i "" "s/'//g" a.txt
    • 在行首行尾加不同内容sed -e 's/^/prefix-&/g;s/$/&-suffix/g' a.txt
      • 单个命令:sed -e 's/.*/prefix-&-suffix/g' a.txt

三、awk:以行/列为单位文本处理工具

  1. awk,其名称得源于它的创始人Alfred Aho、Peter Weinberger和Brian Kernighan姓氏的首个字母。实际上AWK的确拥有自己的语言:AWK程序设计语言,三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。

  2. 语法awk 'BEGIN{ commands } pattern{ commands } END{ commands }'

    • 第一步:运行BEGIN{ commands }语句块中的语句。
      • BEGIN语句块在awk开始从输入流中读取行之前被运行,这是一个可选的语句块,比方变量初始化、打印输出表格的表头等语句通常能够写在BEGIN语句块中。
    • 第二步:从文件或标准输入(stdin)读取一行,然后运行pattern{ commands }语句块,它逐行扫描文件,从第一行到最后一行反复这个过程,直到文件所有被读取完成。
      • pattern语句块中的通用命令是最重要的部分,它也是可选的。
      • 假设没有提供pattern语句块,则默认运行{ print },即打印每个读取到的行。
      • awk读取的每一行都会运行该语句块。
    • 第三步:当读至输入流末尾时,运行END{ commands }语句块。
      • END语句块在awk从输入流中读取全然部的行之后即被运行。
      • 比方打印全部行的分析结果这类信息汇总都是在END语句块中完毕,它也是一个可选语句块。
  3. 常用

    • 内置函数:AWK内置函数主要有以下几种:算数函数、字符串函数、时间函数、位操作函数和其它。
    • 内建变量
      • NF:被分割的字段的数目,默认以空格为分隔符
        • $NF:最后一个字段内容
      • NR:读取的数据行数,即输出行号
        • FNR:对于多个文件,FNR用于读取每个文件的数据行数
  4. 实战

    • 内置函数

      • gsub

      • NF/NR的使用

        • 文本内容123.txt
        1
        2
        123:456:789:111:222:222
        Abc:dd:asdfa:asdfasdfafadfasd
        • 脚本awk -F: '{print NR,$1,$NF}' 123.txt
    • 内建变量

      • touch boy.log girl.log

      • vim boy.log girl.log

        • boy.log
        1
        2
        3
        tom 20 180 last
        tim 20 181
        jack 20 182
        • girl.log
        1
        2
        3
        rose 20 160
        lily 20 161
        han 20 162
      • cat boy.log girl.log

      1
      2
      3
      4
      5
      6
      tom 20 180 last
      tim 20 181
      jack 20 182
      rose 20 160
      lily 20 161
      han 20 162
      • awk ‘{print NF,$NF}’ boy.log
      1
      2
      3
      4 last
      3 181
      3 182
      • awk ‘{print NR,$0}’ boy.log girl.log
      1
      2
      3
      4
      5
      6
      1 tom 20 180 last
      2 tim 20 181
      3 jack 20 182
      4 rose 20 160
      5 lily 20 161
      6 han 20 162
      • awk ‘{print NR,FNR,$0}’ boy.log girl.log
      1
      2
      3
      4
      5
      6
      1 1 tom 20 180 last
      2 2 tim 20 181
      3 3 jack 20 182
      4 1 rose 20 160
      5 2 lily 20 161
      6 3 han 20 162
      • awk ‘{print FILENAME,NR,FNR,$NF,NF}’ boy.log girl.log
      1
      2
      3
      4
      5
      6
      boy.log 1 1 last 4
      boy.log 2 2 181 3
      boy.log 3 3 182 3
      girl.log 4 1 160 3
      girl.log 5 2 161 3
      girl.log 6 3 162 3
    • 查找指定文本并打印

      • 文本文件someInfo.txt
      1
      2
      3
      4
      5
      6
      someInfo|6x66|2015-04-27 13:12:44|dddb7d7bbb5fff|1|6x66|abckefgkzd_V1IkpFusPnC4c|6x66189_1249937_xyz|0|110|2|11|2015-04-27 13:12:45
      someInfo|6x66|2015-04-27 13:56:32|dddb7d7bbb5fff|1|6x66|abckefgpgDO3LK5QRSZogNRs|6x66189_1245481_xyz|1|101|9||2015-04-27 05:00:00
      someInfo|6x66|2015-04-27 13:56:32|dddb7d7bbb5fff|1|6x66|abckefgpgDO3LK5QRSZogNRs|6x66189_1245481_xyz|1|101|2||2015-04-27 05:00:00
      someInfo|6x66|2015-04-27 13:56:32|dddb7d7bbb5fff|1|6x66|abckefgpgDO3LK5QRSZogNRs|6x66189_1245481_xyz|1|101|3||2015-04-27 05:00:00
      someInfo|6x66|2015-04-27 17:13:03|dddb7d7bbb5fff|0|6x66|abckefgQY0tO8D81KEEf1jtQ|6x66189_1249895_xyz|0|110|9|12|2015-04-27 17:13:03
      someInfo|6x66|2015-04-27 17:13:03|dddb7d7bbb5fff|0|6x66|abckefgQY0tO8D81KEEf1jtQ|6x66189_1249895_xyz|0|110|9|12|2015-04-26 17:13:03
      • 查找6x66_1249895_xyz的行并将结果输出到文件
        • 方式1:grep "6x66189_1249895_xyz" some.log >> ss.txt
        • 方式2:awk '/6x66189_1249895_xyz/ {print $0}' some.log >> ss.txt
        • 方式3:awk '{print $0}' some.log | grep 6x66189_1249895_xyz | awk '{print $0}' >> ss.txt
          • 不加第二个awk则输出到文件后不会换行
          • >是覆盖文件,>>则是追加文件尾部
      • 统计某一列的和awk -F '|' '{a+=$11};END{print a}' someInfo.txt
    • web相关

      • 日志文件access.log
        1
        2
        3
        4
        5
        127.0.0.1 - test [02/Mar/2017:00:57:13 +0800] "POST /token.php HTTP/1.1" 200 1082 "-" "curl/7.64.1"
        127.0.0.1 - test [02/Mar/2017:01:50:29 +0800] "POST /token.php HTTP/1.1" 200 1072 "-" "curl/7.64.1"
        127.0.1.1 - test [02/Mar/2017:02:53:56 +0800] "POST /token.php HTTP/1.1" 200 1054 "-" "curl/7.64.1"
        127.0.2.1 - test [02/Mar/2017:03:54:58 +0800] "POST /token.php HTTP/1.1" 200 1054 "-" "curl/7.64.1"
        127.0.0.1 - test [02/Mar/2017:04:57:11 +0800] "POST /token.php HTTP/1.1" 200 14 "-" "curl/7.64.1"
      • 统计每个ip访问次数awk '{a[$1]+=1}END{for(i in a){printf("%d %s\n",a[i], i)}}' access.log
      • 获取访问次数最多的ip并取最后10行 awk '{a[$1]+=1;}END{for(i in a)printf("%d %s\n", a[i], i);}' 日志文件 | sort -n | tail -n 10
      • 当前WEB服务器中连接次数最多的ip netstat -ntu | awk '{print $5}' | sort | uniq -c | sort -nr
      • 查看日志中访问次数最多的前10个ip cat access.log | cut -d ' ' -f 1 | sort | uniq -c | sort -nr | awk '{print $0 }' | head -n 10 | less
    • 游戏log查询

      • 游戏打点日志一般由运营提供,日志格式已跟运营确定且很少会变动,如第一列代表日志名,第二列代表所在区服,第三列是操作时间等

      • 后端应用服务一般由多台机器组成服务集群(假设有10台),玩家请求时由HA或Nginx负载

      • 玩家的某一个操作完成后,记录到当前机器的某个目录下,如玩家消耗某个物品产生一条记录到/tmp/log/Res.log

      • 对于游戏运营商一般都有个管理后台,可以查询玩家所有的操作,假设由于某些原因后台查询的不准确:

        • 假设有个接口:消耗物品A获得物品B
        • 某天有个玩家跟客服反馈说物品A消耗了却没有获得物品B,且客户在管理后台查询不到相应的记录
        • 去admin机器收集后端服务集群的日志(可以具体某天、某区、某种日志)并下载,假设名字为1.tgz~10.tgz
        • 执行脚本,将所有机器的日志合并到a.txt
        1
        2
        3
        4
        5
        6
        7
        8
        for i in `ls *.tgz`
        do
        tar -zxvf $i
        for j in `ls *.log`
        do
        cat $j >> a.txt
        done
        done
        • 执行脚本,筛选反馈问题的玩家数据(第17列为玩家的账户id)awk -F '|' '{if($17=="aaabbb"){print $0}}' a.txt >> b.txt
        • 执行脚本,按操作时间排序并去重(第3列为玩家操作时间)cat b.txt | sort -t '|' -k 3 | uniq >> e.txt
      • 测试数据d.log

        • awk -F '|' '{a[$12]+=$11;}END{for(i in a)printf("%d %s\n", i,a[i] );}' d.log
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        TestLog|60551|2018-04-15 09:05:42|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|30990|998|113|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:44:30|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|31886|20|6001|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:44:34|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|31836|30|6001|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:23:44|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|34812|998|113|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:06:07|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|28994|998|113|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 08:50:18|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|33262|110|113|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:07:58|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|35700|100|104|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 10:06:40|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|31506|200|9101|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:19:02|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|35830|10|645|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:24:24|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|31946|998|113|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 08:43:32|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|31712|10|6001|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:07:29|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|35850|50|104|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 08:53:19|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|31112|300|616|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:06:20|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|27996|998|113|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 08:43:55|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|31692|20|113|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:44:22|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|31921|15|6001|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:19:05|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|35820|10|645|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:51:17|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|31806|100|104|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:07:30|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|35800|50|104|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:44:32|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|31866|20|6001|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:05:29|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|31988|998|113|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:24:08|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|32944|998|113|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:44:16|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|31936|10|6001|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 10:06:21|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|31706|100|9101|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:04:26|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|35724|998|113|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 08:53:17|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|31412|300|616|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:18:58|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|35850|10|645|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 08:53:16|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|31712|1550|616|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 10:07:11|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|31106|200|9101|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:19:07|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|35810|10|645|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:44:37|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|31806|30|6001|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:05:06|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|32858|998|113|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:44:27|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|31906|15|6001|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:04:39|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|34726|998|113|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:04:52|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|33856|998|113|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:23:56|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|33942|998|113|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:05:55|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|29992|998|113|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 10:06:48|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|31306|200|9101|0|1|2|18|60551_1814483_h
        TestLog|60551|2018-04-15 09:19:00|abcdefghijk|1|60551|asdfasdfas23412asdfasdfiisdfui23nklasdf|0|110|35840|10|645|0|1|2|18|60551_1814483_h
  5. 批量数据处理

    • 数据源,来自某打点数据
    • 解压文件tar -zxvf dataLog.tar.gz
    • 切换目录cd dataLog
    • 查看文件ls
    1
    2
    1003.tgz 3030.tgz 5003.tgz 6053.tgz 7039.tgz
    3010.tgz 3057.tgz 5018.tgz 6097.tgz
    • 脚本解压

      • 用此种方式解压后,每个压缩包的内容都解压在当天目录下了
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      for i in *.tgz
      do
      tar -zxf $i
      done


      >ls
      0_xxx.xxx.xxx.xxx_202110281855_247510.tgz
      0_xxx.xxx.xxx.xxx_202110281856_247511.tgz
      0_xxx.xxx.xxx.xxx_202110281856_247512.tgz
      0_xxx.xxx.xxx.xxx_202110281952_247530.tgz
      0_xxx.xxx.xxx.xxx_202110281953_247531.tgz
      ...
      ...
      ...
      1003.tgz
      3010.tgz
      3030.tgz
      3057.tgz
      5003.tgz
      5018.tgz
      6053.tgz
      6097.tgz
      7039.tgz
    • 采用笨拙的方式每个文件双击解压(为了引出接下来的脚本)ls

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      1003
      1003.tgz
      3010
      3010.tgz
      3030
      3030.tgz
      3057
      3057.tgz
      5003
      5003.tgz
      5018
      5018.tgz
      6053
      6053.tgz
      6097
      6097.tgz
      7039
      7039.tgz
    • 进入每个文件夹再解压并删除每个文件夹下的压缩文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    for i in `ls -d */`
    do
    cd $i
    for j in `ls *.tgz`
    do
    tar -zxvf $j && rm $j
    done
    cd ..
    done


    #例如某个目录的内容如下:
    >ls
    0_xx.xxx.xx.xxx_202110281852_247508.tgz
    0_xx.xxx.xx.xxx_202110281852_247508.tgz
    0_xx.xxx.xx.xxx_202110281852_247508.tgz
    ...
    ...
    ...
    xx.xxx.xxx.xxx_data1_user00_log_tlog_20211027_6053_MoneyFlow.log
    xx.xxx.xxx.xxx_data1_user00_log_tlog_20211027_6053_MoneyFlow.log
    xx.xxx.xxx.xxx_data1_user00_log_tlog_20211027_6053_MoneyFlow.log
    ...
    ...
    ...
    • 也可以分别进入每个目录删除已解压过的文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    for i in `ls .`
    do
    if [ -d $i ];then
    cd $i
    echo "**********************************************************"
    echo "enter: $i"
    for j in `ls *.log`
    do
    rm -rf $j
    done
    cd ..
    else
    echo "$i not dir, now: `pwd`"
    fi
    echo "exit: `pwd`"
    echo "**********************************************************"
    done
    • 过滤满足条件的记录
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    for i in `ls *.tgz`
    do
    tar -zxvf $i
    for j in `ls *.log`
    do
    cat $j | grep '1003_127339' >> a.txt
    done
    done

    awk -F '|' '{if($15==2){print $0}}' a.txt >> gem.txt

    awk -F '|' '{if($15==2 && $14==1){print $0}}' a.txt >> pay.txt
    cat pay.txt | sort -t '|' -k 3 | uniq >> payUniq.txt
    awk -F '|' '{a[$12]+=$11;}END{for(i in a)printf("%d %s\n", i,a[i] );}' payUniq.txt

    awk -F '|' '{if($15==2 && $14==0){print $0}}' a.txt >> get.txt
    cat get.txt | sort -t '|' -k 3 | uniq >> getUniq.txt
    awk -F '|' '{a[$12]+=$11;}END{for(i in a)printf("%d %s\n", i,a[i] );}' getUniq.txt
  • 统计每个ip访问的次数awk '{i=$1;a[i]+=1;}END{for(i in a)printf("%d %s \n",a[i],i)}' access.log

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    2093 192.168.10.1
    2 192.168.10.2
    2 192.168.10.3
    1 127.0.0.1
    1259 127.0.0.1
    1 192.168.10.10
    2 192.168.10.4
    2 192.168.10.5
    2 192.168.10.6
    2 192.168.10.7
    2 192.168.10.8
    1 192.168.10.9
    1 192.168.10.18
    1 192.168.10.0
    • 统计访问最多的前10个ipawk '{i=$1;a[i]+=1;}END{for(i in a)printf("%d %s \n",a[i],i)}' access.log | sort -nr |head -n 10

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      2093 192.168.10.1
      1259 127.0.0.1
      2 192.168.10.8
      2 192.168.10.7
      2 192.168.10.6
      2 192.168.10.5
      2 192.168.10.4
      2 192.168.10.3
      2 192.168.10.2
      1 192.168.10.9
    • 获取具体时间段内的日志

      • 日志格式access.log((打印Jun15-20号的日志,不做年份的限制))
      1
      10.2.24.141 - - [19/Jun/2020:09:56:57 +0800] "POST /index.php?mod=api&ver=0.1&SESSION=%7B%22rid%22:%228201_186%22,    %22sec%22:%228201%22,%22pGroup%22:%22default%22,%22tls%22:0%7D HTTP/1.1" 200 121 "-" "-" "-"
      • 处理脚本awk '{split($4, a, "/"); d=substr(a[1],2); if(d>=15 && d<=20 && a[2]=="Jun") { print $0;} }' access.log
      • 日志格式打印Apr 26号的日志)
      1
      127.0.0.1 - - [26/Apr/2018:11:12:48 +0800] "GET /inc.php HTTP/1.1" 200 62437 "-" "Mozilla/5.0 (Macintosh; Intel    Mac OS X  10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36"
      • 处理脚本awk '{split($4, a, "/"); d=substr(a[1],2); if(d==26 && a[2]=="Apr") { print $0;} }' access.log
  1. 处理逗号分隔的值,加入双引号

    • 测试数据a.txt

      1
      2
      3
      1,2,3
      4,5,6
      7,8,9
    • awk处理:awk -F ',' '{print "\""$1"\",\""$2"\",\""$3"\""}' a.txt,$1/$2/$3写法辣眼睛

      • awk -F ',' '{for(i=1;i<=NF;i++){if(i<NF){printf "\""$i"\","} else{printf "\""$i"\"\n"}}}' a.txt
    • sed处理

      • 编辑a.txt

        1
        2
        3
        4
        1,2,3
        4,5,6
        7,8,9
        a,b,c
      • 处理sed -e 's/\([0-9a-zA-Z]\)/\"\1\"/g' a.txt

四、参考

  1. 参考一
  2. 参考二
  3. 参考三
  4. 参考四
  5. 参考五
  6. 参考六