Skip to main content

moregeek program

关于Linux中的awk、sed高级用法与案例,你想知道的都在这!-多极客编程

awk    命令是一种编程语言,用于在linux/unix下对文本和数据进行处理。

而且它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。


sed 命令是利用脚本来处理文本文件。

sed 可依照脚本的指令来处理、编辑文本文件。sed 主要用来自动编辑一个或多个文件、简化对文件的反复操作、编写转换程序等。


在介绍awk和sed的用法之前先放入一些正则表达式,因为后面会依靠正则表达式!

  • ^        行首定位符    ^abc

  • $        行尾定位符    abc$

  • .        匹配单个字符    .bc  a.c  a..

  • *        匹配前导符0到多次    ab*c

  • .*        任意多个字符

  • []        匹配指定范围内的1个字符        [aA]bc

  • [-]        匹配指定范围内的1个字符        [a-z]bc  [0-9]bc  [a-Z0-9]bc

  • [^]        匹配不在指定范围内的字符        [^a]bc  [^a-z0-9]bc

  • \        转义元字符    \.  \$  \1

  • \<        词首定位符    \<abc

  • \>        词尾定位符    abc\>

  • \(..\)        匹配稍后使用的字符的标签        :%s /10.0.0.10/10.0.0.20/

                        :%s /\(10.0.0.\)/\120/

                        :%s /\(10.\)\(0.\)\(0.\)10/\1\2\320/

                        :3,9s/\(.*\)/#\1/

  • x\{m\}        字符x重复出现m次            x\{2\}

  • x\{m,\}        字符x重复出现m次以上        x\{3,\}

  • x\{m,n\}    字符x重复出现m到n次        x\{3,5\

========扩展正则表达式

  • grep 过滤需要加\转义  如:x\{m\}

  • egrep支持扩展元字符不用加\转义符    如:x{m}

  • +        匹配一个或多个前导字符        abc+  [a-z]+bc

  • ?        匹配0个或1个前导字符        ab?c

  • a|b        a或b                abc|cba  

  • ()        组字符                love(abc|cba)ov+  ov+  (ov)+

  • (..)(..)\1\2    标签匹配符            (love)abc\1abc

  • x{m}        字符x重复m次            x{5}

  • x{m,}        字符x重复最少m次            x{5,}

  • x{m,n}        字符x重复最m次到n次        x{5,10}    

POSIX字符类:

表达式            功能                实例

[:alnum:]        字母与数字字符            [[:alnum:]]+

[:alpha:]        字母字符(包括大小写字母)    [[:alpha:]]{4}

[:blank:]        空格与制表符            [[:blank:]*

[:digit:]        数字字母                [[:digit:]]?

[:lower:]        小写字母                [[:lower:]]{5,}

[:upper:]        大写字母                [[:upper:]]+

[:punct:]        标点符号                [[:punct:]]

[:space:]        包括换行符回车等所有空白        [[:space:]]+



sed 流编辑器

sed的返回值只有在命令错误的情况下返回非0,命令正确后不管文件是否被修改都返回为0

命令        功能

a        在当前行后添加一行或多行

c        在新文本中修改(替换)当前行中的文本

d        删除行

i        在当前行之前插入文本

l        列出非打印字符

p        打印行

n        读入下一输入行,并从下一条命令而不是第一条命令开始对其的处理

q        结束或退出sed

!        对所选行以外的所有行应用命令

s        用一个字符串替换另一个

        s 替换标志

        g 在行内进行全局替换

        i 忽略大小写

r        从文件中读

w        将行写入文件

y        将字符转换为另一个字符(不支持正则表达式)

用法:

sed  -r  '//'  /etc/passwd

正则表达式要放在//中


sed -r          # -r表示支持扩展元字符

sed -ri          # -i表示真正的处理并改变文件

sed -rn          # -n表示静默输出,不会将文件中的内容输出到屏幕上

sed -rn 'p'      # 'p'表示sed每读取到一行到文件空间就会再输出一行

sed -ri  's/root/alice/' /etc/passwd  #将文件中的每一行中的root改为alice

sed -ri  's/root/alice/gi' /etc/passwd #将文件中的每一行中所有的root改为alice,并忽略大小写

sed -ri  's/root/alice/gi' /etc/passwd  也可以写为:sed -ri  's#root#alice#gi' /etc/passwd

sed -ri  '/root/g' /etc/passwd         #查找到root的行并删除

sed -ri  '/root/g' /etc/passwd  也可以写为 sed -ri  '\#root#g' /etc/passwd

sed -r 'd' /etc/passwd           #将删除文件中的所有内容

sed -r '3,5d' /etc/passwd         #删除3到5行

sed -r '/root/,5d' /etc/passwd      #找到包含root的行开始往下连续删除5行

sed -r '/root/,+5d' /etc/passwd      #找到包含root的行删除并往下再多删除5行

ed -r '/root/,!d' /etc/passwd        #不包含root的行都删除

sed -r '1~2d' /etc/passwd          #删除奇数行,从1行开始每隔2行删除一行

sed -r '0~2d' /etc/passwd          #删除偶数行,从0行开始每隔2行删除一行

sed -r '2N;s/\n//g' filename        #删除第二行中的换行符

sed -r ':aa;N;s/\n//;b aa ' filename    #全部查找换行符并删除


sed -r  '3d' /etc/passwd     #删除第三行

sed -r  '3{d;}' /etc/passwd     #删除第三行,  ;后面可以跟多个命令

vim中  3,5s/\(.*\)/#\1/            #表示将3到5行前面加上#

vim中  3,5s/.*/#&/            #表示将3到5行前面加上#

                    &表示查找之后匹配到的字符串

sed -r '3,5s/(.*)/#\1/'    /etc/passwd        #表示将3到5行前面加上#

sed -r '3,5s/.*/#&/'    /etc/passwd        #表示将3到5行前面加上#

sed -r '/root/s/(.*)/#\1/' /etc/passwd        #将所有包含root的行前面加上#

sed -r 's/(.)(.)(.*)/\1abc\2\3/' /etc/passwd    #将所有行中的第二个字母前加上abc

sed -r '/root/r /root/1.txt' /etc/passwd     #在包含root行的下一行读取/root/1.txt文件

sed -r '2iabc' /etc/passwd            #在第二行的上一行插入abc的新行

sed -r '2aabc' /etc/passwd             #在第二行的下一行插入abc的新行

sed -r '2cabc' /etc/passwd             #在第二行替换为abc的新行

sed -r '2c\abc\' /etc/passwd             #在第二行替换为abc的新行

sed -r '/adm/{n;d}'                #表示查找到adm后的下一行被删除

                        #n表示查找完后再再获取下一次命令

sed -r '/adm/{n;s/sbin/nobody/}'        #查找adm后再查找sbin替换为nobody(只替换一行)

暂存空间:    h H  g G

暂存空间中默认会有一个空行


h g :覆盖

H G :追加

h H :放入暂存空间

g G :从暂存空间取出

sed -r '1h;$G' /etc/passwd            #将第一行覆盖暂存,处理到最后一行时再将第一行追加到模式空间

sed -r '1{h;d};$G' /etc/passwd            #将第一行覆盖暂存后并删除,最后一行时将第一行追加到模式空间

sed -r '1h;2$g' /etc/passwd            #将第一行覆盖暂存,处理2到最后一行时覆盖到模式空间

sed -r '1h;2,3H;$G' /etc/passwd            #第一行覆盖暂存,2到3行追加,最后一行时再追加到模式空间

sed -r '/^[ \t]*#|^[ \t]*$/d' /etc/passwd    #删除注释以及空行

sed -r '/^[ \t]*(#|$)/d' /etc/passwd        #删除注释以及空行



awk用法

BEGIN{}            {}             END{}

行处理前        行处理        行处理后


BEGIN{} 通常同于定义一些变量,例如BEGIN{FS=":";OFS="---"}

$0:    awk变量$0保存当前记录的内容

NR:    显示行号(如果打开多个文件会当成一个文件显示行号)

FNR:    显示行号(如果打开多个文件会分别显示顺序行号)

NF:    保存记录的字段数,$1,$2,..$100,表示一共有多少个$

FS:    输入字段分隔符,默认空格

RS: 默认的输入记录分隔符,默认情况下是换行。

ORS: 输出记录分隔符,默认是换行。


awk -F":" '{print NR,$0}'       #打印文件所有内容并显示行号

awk -F'[ :\t]' '{print $1,$2}'    #支持多种字符一起分割,遇见其中一种就分割一次

awk 'BEGIN{FS=":"}{print $1}'    #定义分隔符为 ":"

awk 'BEGIN{FS=":";OFS="++"}/^root/{print $1,$2}'     # $1和$2之间输出的间隔是默认为空格,现在设定为之间以++形式输出,并查找到以root开头的行

awk -F":"'BEGIN{RS=" "}{print $0}'        #默认读取文件时,遇到换行符就代表一条记录结束,现在定义为遇到空格就是一条记录

awk 'BEGIN{ORS=" "}{print $0}'            #ORS默认将$0一条记录打印到屏幕时会进行回车,现在定义打印完时进行输出一个空格

printf

awk -F":" '{printf "%-15s %-10s %-15s\n",$1,$2,$3}' /etc/passwd

%s 字符类型

%d 数值类型

%f 浮点类型

15 占15字符

- 表示左对齐,默认是右对齐

printf默认不会在行尾自动换行,加\n表示一条记录后换行

awk -F":"'$1 ~/^root/' /etc/passwd    #输出$1中包含以root开头的记录

awk -F":"'$NF!~/bash$/' /etc/passwd     #输出不是以bash结尾的记录

awk -F":" '{if($3>300) {print $3} else{print $1}}' #if语句匹配

awk -F":" '$3 * 10 > 500' /etc/passwd  ### awk -F":" '{if($3*10>500){print $0}}'

awk -F":" '$1~/root/ && $3<=15'        #逻辑与

awk -F":" '$1~/root/ || $3<=15'        #逻辑或

awk -F":" '!($1~/root/ || $3<=15)'    #逻辑非    

awk -F":" '{if($3>0 && $3<1000){i++}} END{print i} #统计系统用户

【if...else语句】:

awk -F":"'{if($3==0){count++}else{i++}}END{

    print"管理员个数"count;print"普通用户个数"i}' /etc/passwd

【if...else if...else 语句】:

awk -F":"'{if($3==0){i++} else if($3>999){k++} else{j++}}END{

    print i;print k;print j}' /etc/passwd


awk -F":" '^root{i=1;while(i<=NF){print $i;i++}}'     #打印所有分割列

 =====【数组】

awk -F":"'{username[++i]=$1} END{print username[1]}' /etc/passwd

awk -F":"'{username[i++]=$1} END{print username[0]}' /etc/passwd

一些实战案例~

(统计/etc/passwd中各种类型shell的数量)

awk -F":" '{user[j++]=$1,} END{for (i in user){print i,user[i]}}' /passwd

#变量i是索引


(网站访问状态统计《当前实时状态》)

#netstat -anpt | grep ":80" |awk '{access_stat[$NF]++} END{

    for (i in access_stat){print i,access_stat[i]}}'


#ss -an | grep ":80" |awk '{access_stat[$NF]++} END{

    for (i in access_stat){print i,access_stat[i]}}'


(统计访问本主机的ip数量之次数)

#netstat -anpt |grep ":80" |awk -F":" '!/LISTEN/{ips[$(NF-1)]++} END{

    for (i in ips){print i,ips[i]}}' |sort -k2 -rn


(统计日志文件中的ip请求次数)

awk '/22\/Mar\/2017/{ips[$1]++} END{

for(i in ips){if(ips[i]>100){print i,ips[i]}}}' test.log |sort -k2 -rn


(统计用户名为4个字符的用户)

awk -F":"'$1~/^....$/{count++;print $1}END{

    print "count is: "count}' /etc/passwd


awk -F":"'length($1)==4{count++;print $1}END{

    print "count is: "count}' /etc/passwd

【awk中使用外部变量】


1. 在双引号的情况下使用

#var="bash"

#echo "unix script" |awk "gsub(/unix/,\"$bash\")"  

~~gsub()是一个函数,有sub和gsub两种,可以进行查找替换,gsub是全局性查找


2.在单引号的情况下使用

#var="bash"

#echo "unix script" |awk 'gsub(/unix/,"'"$var"'")'

#df -h |awk '{if(int($5)>10){print $6":"$5}}'

~~int()是一个函数,只取整数

#i=10

#df -h |awk '{if(int($5)>'''$i'''){print $6":"$5}}'

~~必须使用''' '''或"'" "'"才能使外部变量在awk中生效

awk参数 -v (建议使用)

#echo "unix script" |awk -v var="bash" 'gsub(/unix/,var)'

#awk -v user="root" -F":"'$1==user' /etc/passwd

 


【【Nginx 日志分析】】

日志格式:

这个日志输出格式是nginx.conf文件中定义的,是可以按照自己的项目进行修改的,一般情况都跟下面这个类似!

log_format main '$remote_addr - $remote_user [$time_local] "$request"'

                '$status $body_bytes_sent "$http_referer"'

                '"$http_user_agent" "$http_x_forwarded_for"';

                

                

日志文件中有以下一些条目,如:

114.242.15.54 - - [22/Mar/2017:09:42:08 +0800] "GET /css/20151103Style.css HTTP/1.1" 200 9041 "http://sz.cdn-my.mobiletrain.org/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36"



使用awk分割占的位置:

$remote_addr        $1

$time_local        $4

$request        $7

$status            $9

$body_bytes_sent    $10



(统计来访次数超过100次的ip):

#awk '/22\/Mar\/2017/ {ips[$1]++}END{for (i in ips){if(ips[i]>100){print i,ips[i]}}}' sz.org.log

#awk '/22\/Mar\/2017/ {ips[$1]++}END{for (i in ips){print i,ips[i]}}' sz.org.log |awk '$2>100'

(统计2017年9月5日,每个URL访问内容总大小($body_bytes_sent)):

#awk '/05\/Sep\/2017/{size[$7]+=$10}END{for (i in size){print i,size[i]}}' sz.org.log |sort -k2rn |head

(统计来访ip和访问时的状态码):

#awk '/05\/Sep\/2017/{ip_code[$1" "$9]++}END{for (i in ip_code){print i,ip_code[i]}}' sz.org.log |sort -k2rn |head

(统计来访ip和访问时的状态码404):

#awk '/05\/Sep\/2017/{if($9=="404"){ip_code[$1" "$9]++}}END{for(i in ip_code){print i,ip_code[i]}}' sz.org.log |sort -k2rn

(统计前一分钟的pv量):

#date=`date -d '-1 minute' +%d/+%b/%Y:%H:%M` ;awk -v date=$date '$0 ~ date {i++}END{print i}' sz.org.log

(统计8:30 - 9:00之间来访IP出现404的次数):

#awk '$4>="[05/Sep/2017:08:30:00" && $4<="[05/Sep/2017:09:00:00"{if($9=="404"){ip_code[$1" "$9]++}}END{for (i in ip_code){print i,ip_code[i]}}' sz.log

(统计某个时间段内所有状态码的次数):

#awk '/05\/Sep\/2017/{code[$9]++;total++}END{for (i in code){printf i"\t";printf code[i]"\t";printf "%.2f",code[i]/total*100;print "%"}}' sz.log

#awk '/05\/Sep\/2017/{code[$9]++;total++}END{for (i in code){printf i"\t";printf code[i]"\t";printf "%.2f%\n",code[i]/total*100}}' sz.log

~~输出结果为:

200        544        34.45%



-------------------------------------------------

(定期删除/date目录下修改时间大于7天的文件):    

#find /date -mtime +7 |xargs rm -rf       


(只保留最近2份的文件,其他的文件都删除):       

#ls -t /date/*.tar.gz |awk 'NR>2' |xargs rm -f    

-------------------------------------------------


©著作权归作者所有:来自51CTO博客作者GuanLu的原创作品,如需转载,请注明出处,否则将追究法律责任
关于Linux中的awk、sed高级用法与案例,你想知道的都在这!
https://blog.51cto.com/u_15163980/2713991

Linux服务器集群——集群概述、配置-多极客编程

概述:集群概述:MySQL 复制技术,通过集群实现负载均衡,解决高并发,高可用HA提升服务可用性,还可以远程灾备,保证数据有效性原理 解释:在主库上把数据更改(DDL DML DCL)记录到二进制日志(Binary Log)中。备库I/O线程将主库上的日志复制到自己的中继日志(Relay Log)中。备库SQL线程读取中继日志中的事件,将其重放到备库数据库之上。环境:全新服务器-互相通信,全新安装

makefile使用.lds链接脚本以及 常用命令 解析-多极客编程

1.分析一个简单的.lds链接脚本  例1,假如现在有head.c init.c nand.c main.c这4个文件:1.1 首先创建链接脚本nand.lds:1 SECTIONS { 2   firtst      0x00000000 : { head.o init.o nand.o}3   second     0x30000000 : AT(4096) { main.o }4 }SECT

26.3.4.2内核下的I2C驱动(一)-多极客编程

1.硬件协议1.1mini2440 I2C设备如图所示1.2 I2C协议如下:1.3启动和停止信号如下图1.4 I2C总线数据传输时序:1.5 2440只负责发送,不知道数据含义,只有外设知道。如何写一个字节?参考AT24CXX手册 。注意:I2C设备读之前先写!2.软件框架2.1总线-设备-驱动模型如下图所示  把某个结构体,左右的放入链表,一一比较,匹配调用probe函数   设备链表 dri

Linux下mongodb环境经常挂掉解决方法脚本-多极客编程

mongodb环境经常挂掉,监控或复活的脚本。经常挂掉肯定有非常规原因。看了一下日志,发现存在stop记录,我就纳闷了,没人操作他还会自己stop。这明显不是挂掉了,于是到history中看了下同事的启动命令:/usr/local/mongodb/bin/mongod --dbpath=/usr/local/mongodb/data/ --logpath=/data/mongodb.log --l

Linux轻量级CC攻击防御工具,秒级检查、自动拉黑和释放-多极客编程

一、功能申明分享之前我必须先申明一下,众所周知,DDoS攻击指的是分布式拒绝服务。而CC攻击只是DDoS攻击的一种,本文所阐述的CC攻击,指的是单个IP达到我们设定好的阈值并发请求,而非海量IP的低并发攻击!对于个人低配服务器,除了使用CDN来防护,至少我是没有想到如何抵挡海量IP攻击的!因为每个IP都模拟正常的用户浏览器请求,并不会触发防御阈值,同时来1000个,甚至上万个,个人低配服务器的带宽

Linux上安装gitbook并拉取git项目编译-多极客编程

Linux上安装gitbook并拉取git项目编译1、下载node注意:我尝试了用 node 14.x,gitbook会报莫名其妙的错误,这里推荐安装 node 12.x下载地址:https://nodejs.org/dist/latest-v12.x我下载的是:node-v12.22.1-linux-x64.tar.xz 2、上传到Linux服务器,解压# 解压tar -xvf node-v12

使用shell+python脚本实现系统监控并发送邮件-多极客编程

1、编辑shell脚本[root@web03 ~/monitor_scripts]# cat inspect.sh  #!/bin/bash # 设置磁盘的阀值 disk_max=90 # 设置监控inode的分区 partition="/dev/sda3" # 设置磁盘inode使用率的阀值 disk_inode_use=90 # 这是mem的阀值 mem_max_use=90 # C

shell脚本变量-多极客编程

既然是变量,自然分变量名和变量值,在使用的时候一定要注意哪些地方需要用变量名,哪些地方需要用变量的值。自定义变量shell变量不需要声明,随用随定义,给变量赋值的时候要注意shell是空格敏感的使用{}确定变量的范围是个好习惯$NEWENV =123                #等号前面有空格,不行 NEWENV: command not found    $NEWENV= 123      

shell实例流程控制&函数-多极客编程

条件if-then-elif-then-fiif的条件部分经常使用test EXPRESSION或[ EXPRESSION ]实现,test的用法可以参见testif 条件1        #if 条件1;then   then    执行语句1 elif 条件2      #elif 条件2;then then     执行语句2   else 执行语句3 fi    #条件结束标识,即将

从0开始学习shell--tr工具的使用-多极客编程

tr工具Tr 用于字符转换,替换和删除用法一:命令的执行结果交给tr处理,str1用于查询,str2用于转换处理Command | tr ‘str1’ ‘str2’用法二:tr处理的内容来自文件,< 标准输入Tr ‘str1’ ‘str2’ < filename用法三:匹配文件中的str1进行相应的操作,如删除操作tr option ‘str1’ < filename -d 删除

从0开始学习shell--tr工具的使用-多极客编程

tr工具Tr 用于字符转换,替换和删除用法一:命令的执行结果交给tr处理,str1用于查询,str2用于转换处理Command | tr ‘str1’ ‘str2’用法二:tr处理的内容来自文件,< 标准输入Tr ‘str1’ ‘str2’ < filename用法三:匹配文件中的str1进行相应的操作,如删除操作tr option ‘str1’ < filename -d 删除

shell脚本实现系统安全巡检-多极客编程

在使用脚本前需要安装:ag命令安装方式如下:[root@xinsz08-63 LinuxCheck]# yum install epel-release[root@xinsz08-63 LinuxCheck]# yum install the_silver_searcherag的日常使用: ag类似于grep和find,但是执行效率比后两者高ag -g a.txt 查找名字为a.txt的文件 ag