Linux的Shell脚本——day6——awk文本检索

自动对齐
  column -t 文本
  echo '内容' | column -t

[Lyu@root ~]#awk -F: 'BEGIN{print "用户名","UID","家目录"}{print $1,$3,$(NF-1)}END{print "一 共"NR"行"}' /etc/passwd | column -t
用户名           UID    家目录
root             0      /root
bin              1      /bin
daemon           2      /sbin
adm              3      /var/adm
lp               4      /var/spool/lpd
………………(太长就不全显示了)
一共42行

排序:
  sort [选项]  排序文本
  选项:
   -n表示按数字顺序升序排列
   -r表示反序,如果要数组降序排列就要用-nr
   -k可以指定按第几个字段来排序
  
  也可以用管道发给sort:  cat 文本 | sort -nr


awk  选项  '条件{指令}'  文件
    支持拓展正则
    不写指令的时候默认是{print} ,打印符合条件的行的全部内容

条件

命令格式 作用 例子 解释
'/正则表达式/{命令}' 按照正则表达式匹配行,匹配成功后执行命令 awk '/Accept/{print $11}' /var/log/secure 查看哪些IP成功远程登陆了
'BEGIN{指令}' 在读文件前执行一次 awk 'BEGIN{print "开始打印"}{print $(NF-1)}' test.txt 先输出“开始打印”然后输出倒数第二列的值
awk 'BEGIN{x=1;y=2.5;print x+y}' 如果awk中只有BEGIN,则可以不跟文件,把awk可以当计算器使用
awk 'BEGIN{x=0}/bash$/{x++}END{print "一共"x"行"}' /etc/passwd 统计一共有多少个以bash为解释器的用户,先用BEGIN创建x初始化为0,然后判断是不是bash结尾如果是就让x+1,最后输出一共有多少行
'END{指令}' 在读完文件后执行一次
awk '{print $NF}END{print "打印结束"}' test.txt 输出最后的值最后输出“打印结束”
awk 选项 'BEGIN{指令1}条件{指令2}END{指令3}'   执行指令1,然后一行一行读文件,如果哪行满足条件,执行指令2,文件完全读完后,执行指令3
'!/正则表达式/{命令}' 按照正则表达式匹配行,匹配失败后执行命令
'$数字n~/正则表达式/{命令}' 对每行的第n列进行正则匹配,匹配成功后执行命令 awk -F: '$5~/^root/' /etc/passwd 每行的第5列进行匹配看,这行这列的数据是不是root开头的(注意这里不是行首匹配了),如果是就输出所有(不写指令默认输出所有)
'$数字n!~/正则表达式/{命令}' 对每行的第n列进行正则匹配,匹配失败后执行命令
'变量==具体值{命令}' 变量和具体值完全相同,执行命令,具体值可以是变量,不是变量用" "标示出来
'变量!=具体值{命令}' 变量和具体值不相同,执行命令,具体值可以是变量,不是变量用" "标示出来
'变量>=具体值{命令}' 变量大于等于具体值,执行命令,具体值可以是变量,不是变量用" "标示出来
'变量<=具体值{命令}' 变量小于等于具体值,执行命令,具体值可以是变量,不是变量用" "标示出来
'变量>具体值{命令}' 变量大于具体值,执行命令,具体值可以是变量,不是变量用" "标示出来
'变量<具体值{命令}' 变量小于具体值,执行命令,具体值可以是变量,不是变量用" "标示出来
'逻辑判断1&&逻辑判断2' 满足判断1并且满足判断2的匹配成功
'逻辑判断1||逻辑判断2' 满足判断1或者满足判断2的匹配成功

变量

变量名 作用 例子 解释
自定义 自定义的一个变量,如果没有赋予初始值,默认为0 x=2;x++ 定义一个变量x,赋予初始值为2,然后进行自+1操作
$数字n 文本的第n列,但是$0代表文本当前行的全部内容
NR 当前行号 df -h | awk 'print NR' 输出一共多少个挂载
NF 当前行一共的列数 df -h | awk 'print NF' 输出df一共显示多少列数据
$(NF-数字n) 当前行倒数第(n+1)列 awk '{print $(NF-1)}' test.txt 打印文件的倒数第二列
awk -F: '{print $1,$NF}' /etc/passwd 打印用户的解释器,答应每行第一列和最后一列
数组名[下标] 自定义数组,数组的下标可以是字符串,不一定要是数字 awk 'BEGIN{a[0]=0;a[1]=11;a[2]=22; for(i in a){print i,a[i]}}' 遍历打印数组中所有的数组下标和对应的数组值

指令

命令格式 选项 & 作用 例子 解释
print 编辑命令   如果有多个可以用 ; 分割开来
'条件{print $列数}' 按照要求答应相应列数,默认分割符号是空格和制表符 df-h | awk '{print $1,$4}' test.txt 打印文件系统和可用容量
-F 指定分割符号,F后面指定可以是任何符号(如果用\,需要写成\\),[ ]里面可以写多个分割符 awk -F: '{print $1,$3}' /etc/passwd 打印用户名和其UID
awk -F[:/] '{print $2,$7}' 以:和/作为分割符输s出第一列和第七列数据
'条件{if(判断){命令}else{命令}}' 多分支判断控制 awk -F: '{if($3<1000){x++}else{y++}}END{print "系统用户个数为:"x;print "管理员创建用户个数为:"y' /etc/passwd 检索判断出系统用户和自创用户个数

注意:
    1.如果awk中需要用常量需要用" "标示出来,而变量可以不用$,只要不是" "里面的都当成变量
    2.在使用的时候print可以用逗号分割,打印的时候会出来空格,也可以不用

awk -F: '{print $1,"的解释器:",$NF}' /etc/passwd    #  输出示例:root 的解释器: /bin/bash (这三个部分间都有一个空格)
awk -F: '{print $1"的解释器:"$NF}' /etc/passwd    #  输出示例:root的解释器:/bin/bash(之间没有空格)

    3.多条命令可以用 ; 隔开,这杨可以一次执行
    4.在脚本中如果有变量参与,可以用分号把原有命令分割开来 awk -F: '$1=="'$i'"{print $2}' /etc/shadow 这里$i就是脚本中定义的变量,如果不考虑变量内部格式应该是 '$1=="root"{print $2}' 如果想把root单独取出就把root前的$1=="用' ' 隔离开来,"{print $2}也用 ' ' 隔离开,中间的root就可以用变量代替,因为他追根究底是一个字符串,然后作为一个参数给awk
    5.在awk中的for循环for(i in a) 循环的是a数组的下标,如果要遍历输出a数组的内容,用下面的语句for(i in a){print a[i]},而且数组的下标可以是字符串,不一定要是数字
    6. awk '{a[$1"--"$7]++}END{for(i in a){print i,a[i]}}' /var/log/httpd/access_log 用来检索统计出一个ip访问某个网页多少次,/var/log/httpd/access_log的第一列是ip,第七行是访问的网络地址,而用的是一个数组a,其下标是 [ip--地址] ,因为awk的的数组下标可以是随意的字符串,这样用下标来标示是ip和地址,相同的ip和地址就放在一起存储,有一个就+1,最后可以完成统计。


统计次数:
    公式:awk -F分割符号 '{a[$第几列]++}END{for(i in a){print i,a[i]}}' 文件
    用来统计文件中以某列为标识,统计该标识出现多少行。

检查网页是否遭受DOS攻击

awk '{a[$1" "$7]++}END{for(i in a){print i,a[i]}}' /var/log/httpd/access_log | awk '$3>1000{print $1,$2}'

    自动检测某个网页,被同一个IP访问超过1000次,这IP就算攻击者

你可能感兴趣的:(Linux,shell)