文本三剑客

举了一些工作中常用的例子介绍grep,awk,sed三种文本工具
内容 隐藏
3 3. 文本处理三剑客之 awk

1. 文本处理三剑客之 grep

1.1. 作用:

文本搜索工具,根据用户指定的“模式”对目标文本逐行进行匹配检查;打印匹配到的行

1.2. 模式:

由正则表达式字符及文本字符所编写的过滤条件

1.3. 格式:

grep [OPTIONS] PATTERN [FILE…]

1.4. 选项:

-color=auto 对匹配到的文本着色显示  

-m  # 匹配#次后停止  

-v 显示不被pattern匹配到的行,即取反  

-i 忽略字符大小写  

-n 显示匹配的行号  

-c 统计匹配的行数  

-o 仅显示匹配到的字符串  

-q 静默模式,不输出任何信息  

-A # after, 后#行  

-B # before, 前#行  

-C # context, 前后各#行  

-e 实现多个选项间的逻辑or关系,如:grep –e ‘cat ' -e ‘dog' file  

-w 匹配整个单词  

-E 使用ERE,相当于egrep  

-F 不支持正则表达式,相当于fgrep  -f file 根据模式文件处理  

-r  递归目录,但不处理软链接  

-R  递归目录,但处理软链接

1.5. 面试题:

1.5.1. 取两个文件的相同行

grep -f /root/123 /root/haha

1.5.2. 分区利用率最大的值

df | grep '^/dev' | tr -s ' ' % | cut -d% -f5 |sort -nr |head -1

df | grep '^/dev' | grep -oE '[0-9]{,3}%' | tr -d '%' |sort -nr | head -1
#grep -oE '[0-9]{,3}%'   #只显示匹配拓展正则表达式的内容,以数字开头匹配0-3次后面跟着%

df |grep '^/dev/' |grep -oE '[0-9]{,3}%'|grep -Eo '[0-9]+' |sort -n | tail -1
#grep -Eo '[0-9]+'             #只匹配数字将百分号进行去除

1.5.3. 不显示 /etc/profile文件中的注释行(#开头)和空行

grep -v '^#' /etc/profile | grep -v '^$'

grep -v '^#\|^$' /etc/profile 

grep -v "^\(#\|$\)" /etc/profile

grep -Ev "^(#|$)" /etc/profile

egrep -v "^(#|$)" /etc/profile

egrep -v '^(#|$)' /etc/httpd/conf/httpd.conf

1.5.4. 查看网卡地址

ifconfig ens33 | grep -Eo '([0-9]{1,3}.){3}[0-9]{1,3}' |head -1

echo "([0-9]{1,3}.){3}[0-9]{1,3}" > lala
 ifconfig ens33 | grep -Eof lala | head -1      #通过-f选项直接调用文件中的内容

1.5.5. 算出所有人的年龄总和 xiaoming=20 xiaohong=18 xiaoqiang=22

cat age | cut -d= -f2 | paste -d+ -s | bc

cat age | cut -d= -f2 | tr -t '\n' + | grep -Eo '.*[0-9]' |bc

cat age | grep -Eo '[0-9]+' |tr -t '\n' + | grep -Eo '.*[0-9]' |bc      
#grep -Eo '[0-9]+'             # 将所有的数字匹配显示出来

2. 文本处理三剑客之 sed

2.1. sed 工作原理

Sed是从文件或管道中读取一行,处理一行,输出一行;再读取一行,再处理一行,再输出一行,直到最后一行。每当处理一行时,把当前处理的行存储在临时缓冲区中,称为模式空间(Pattern Space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。一次处理一行的设计模式使得sed性能很高,sed在读取大文件时不会出现卡顿的现象。如果使用vi命令打开几十M上百M的文件,明显会出现有卡顿的现象,这是因为vi命令打开文件是一次性将文件加载到内存,然后再打开。Sed就避免了这种情况,一行一行的处理,打开速度非常快,执行速度也很快

2.2. 基本用法

2.2.1. 格式:

sed [option]... 'script;script;...' [inputfile...]

2.2.2. 选项:

-n 不输出模式空间内容到屏幕,即不自动打印  

-e 多点编辑  

-f FILE 从指定文件中读取编辑脚本  

-r, -E 使用扩展正则表达式  

-i.bak 备份文件并原处编辑  

-s 将多个文件视为独立文件,而不是单个连续的长文件流

说明:

 -ir 不支持
 -i -r 支持
 -ri  支持
 -ni  会清空文件

2.2.3. script格式:’地址命令’

2.2.4. 地址格式:

  1. “`sh
    1. 不给地址:对全文进行处理
    2. 单地址: #:指定的行,$:最后一行 /pattern/:被此处模式所能够匹配到的每一行
    3. 地址范围: #,# #从#行到第#行,3,6 从第3行到第6行 #,+# #从#行到+#行,3,+4 表示从3行到第7行 /pat1/,/pat2/ #,/pat/ /pat/,#
    4. 步进:~ 1~2 奇数行 2~2 偶数行

      “`

2.2.5. 命令:

p       #打印当前模式空间内容,追加到默认输出之后  

Ip      #忽略大小写输出  

d        #删除模式空间匹配的行,并立即启用下一轮循环  

a [\]text   #在指定行后面追加文本,支持使用\n实现多行追加  

i [\]text    #在行前面插入文本  

c [\]text   #替换行为单行或多行文本  

w file      #保存模式匹配的行至指定文件  

r file      #读取指定文件的文本至模式空间中匹配到的行后  

=           #为模式空间中的行打印行号  

!           #模式空间中匹配行取反处理  

q           #结束或退出sed

2.2.6. 查找替代:

s/pattern/string/修饰符 查找替换,支持使用其它分隔符,可以是其它形式:s@@@,s###    

#替换修饰符:  
​   g       #行内全局替换  
​   p       #显示替换成功的行  
​   w /PATH/FILE    #将替换成功的行保存至文件中  
​   I,i     #忽略大小写

2.2.7. 练习

不显示空行和注释行

sed -e '/^#/d' -e'/^$/d' /etc/httpd/conf/httpd.conf

sed '/^#/d;/^$/d' /etc/httpd/conf/httpd.conf

grep -Ev '^#|^$' /etc/httpd/conf/httpd.conf

获取分区利用率

df | sed -En '/^\/dev\//s@.* ([0-9]+)%.*@\1@p'
#/^\/dev\//            #地址范围^\/dev\/               #即地址范围为以/dev/开头的行
#s@.* ([0-9]+)%.`*`@\1@p       #s:替换       #*空格([0-9]+)%.`*`表示将空格后面跟着数字匹配一次或多次然后跟着百分号的这部分数字作为一个变量1         #\1表示调用变量1          #p:输出

df | sed -En '/^\/dev\//s@ .* ([0-9]+%).*@\1@p'
#主题思路与上面一种相似,只不过上面是只显示利用率数值,这种可以同时显示数值以及磁盘名
#第一个@后面跟了一个空格这样,前面的磁盘名因为这个空格所以和后面的.*分开了,也被匹配到了,所以会输出,如果不加空格因为.*会直接匹配到利用率的数字前这样只会输出利用率的数字了就是上一种解法

df | sed -rn '/^\/dev\/sd/ s#([^[:space:]]+[[:space:]]+){4}(.*)%.*#\2#p'

df | sed -rn '/^\/dev\/sd/ s#(\S+\s+){4}(.*)%.*#\2#p'

搜索替换和&

sed -nE 's@r..t@&er@gp' /etc/passwd
#&表示之前匹配的内容即r..t       #&er表示在匹配的内容后加上er

取ip地址

ifconfig ens33 |sed -nr "2s@[^0-9]+([0-9.]+).*@\1@p"
#2:第二行             #s:表示替换
#[^0-9]+:非数字匹配一次或多次,即ip地址前面的部分 #([0-9.]+):数字与点号匹配一次或多次,即ip地址部分
#.*:任意长度任意字符匹配,即ip地址后面部分
#\1:表示调用之前的([0-9.]+),即将第二行整行内容替换为括号中的内容,即ip地址部分
#p:输出\1的内容,即输出ip地址

ifconfig ens33 | sed -En '2s@^[^0-9]+([0-9.]{7,15}).*@\1@p'
#([0-9.]{7,15}):限定匹配次数最少7次,最多15次

ifconfig ens33| sed -n '2s@^.*inet @@p' | sed -n 's@netmask.*@@p'
#2s@^.*inet @@p:匹配任意字符任意长度加inet加空格,然后替换为空输出。即将ip地址前的内容去掉
#s@netmask.*@@p:匹配netmask加上任意长度的任意字符,然后替换为空输出。即将ip地址后面的内容去掉

ifconfig ens33 | sed -n '2s@^.*inet @@;s@ netmask.*@@p'

ifconfig eth0 | sed -rn '2s@(.*inet )([0-9].*)(netmask.*)@\2@p'

取基名和目录名

echo "/etc/sysconfig/network-scripts/" |sed -r 's#(^/.*/)([^/]+/?)#\2#'     #取基名

echo "/etc/sysconfig/network-scripts/" |sed -r 's#(^/.*/)([^/]+/?)#\1#'     #取目录

取文件的前缀和后缀

echo a.b.c.gz |sed -En 's/(.*)\.([^.]+)$/\1/p'              #取文件名

echo a.b.c.gz |sed -En 's/(.*)\.([^.]+)$/\2/p'              #取后缀名

echo a.b.c.gz |grep -Eo '.*\.'                              #取文件名

echo a.b.c.gz |grep -Eo '[^.]+$'                            #取后缀名

echo a.b.tar.gz | sed -rn 's@.*\.([^.]+)\.([^.]+)$@\1.\2@p'

将非#开头的行加#

sed -En 's@(^[^#].*)@#\1@p' /etc/fstab

sed -rn '/^#/!s@^@#@p' /etc/fstab
#/^#/!:先匹配以#开头的行,在通过!取反。即选出所有非#开头的行

将#开头的行删除#

sed -ri.bak '/^#/s/^#//' /etc/fstab

修改内核参数

sed -nr '/^GRUB_CMDLINE_LINUX/s@"$@ net.ifnames=0"@p'/etc/default/grub

sed -rn '/^GRUB_CMDLINE_LINUX=/s@(.*)"$@\1 net.ifnames=0"@p'/etc/default/grub

sed -rn '/^GRUB_CMDLINE_LINUX=/s@"$@ net.ifnames=0"@p'/etc/default/grub

修改网卡名称

centos7、8
sed -i '/GRUB_CMDLINE_LINUX=/s#quiet#& net.ifnames=0#'/etc/default/grub
sed -ri '/^GRUB_CMDLINE_LINUX=/s@"$@ net.ifnames=0"@'/etc/default/grub
grub2-mkconfig -o /boot/grub2/grub.cfg

Ubuntu
grub-mkconfig -o /boot/grub/grub.cfg

查看配置文件

过滤掉空行和#开头的行

sed  -r '/^(#|$)/d' /etc/httpd/conf/httpd.conf
sed  -r  '/^#|^$/d' /etc/httpd/conf/httpd.conf

可以排除行首后加多个空白符之后有#这种行

sed  -n '/^$/d;/^[[:space:]]*#/!p' /etc/httpd/conf/httpd.conf
sed  -n  -e '/^$/d' -e '/^[[:space:]]*#/!p' /etc/httpd/conf/httpd.conf

注意:以下前后顺序不同,执行效果不同

sed  -n '/^[[:space:]]*#/!p;/^$/d' /etc/httpd/conf/httpd.conf
sed  -n  -e '/^[[:space:]]*#/!p' -e '/^$/d' /etc/httpd/conf/httpd.conf

引用变量

[root@centos8 ~]#echo|sed "s/^/$RANDOM.rmvb/"
 5242.rmvb

[root@centos8 ~]#echo|sed 's/^/$RANDOM.rmvb/'
 $RANDOM.rmvb

修改配置文件

sed  -e '/^#<VirtualHost/,/^#<\/VirtualHost>/s@#@@' -e'/^#NameVirtualHost/s@#@@' /etc/httpd/conf/httpd.conf

变量实现多点编辑配置文件

sed -ri.bak -e 's@^Listen 80@Listen '$port'@' -e "/ServerName/c ServerName `hostname`:$port" /etc/httpd/conf/httpd.conf

2.3. 高级用法

2.3.1. sed 中除了模式空间,还另外还支持保持空间(Hold Space),利用此空间,可以将模式空间中的数据,临时保存至保持空间,从而后续接着处理,实现更为强大的功能。

2.3.2. 常见的高级命令:

P       #打印模式空间开端至\n内容,并追加到默认输出之前  

h       #把模式空间中的内容覆盖至保持空间中  

H       #把模式空间中的内容追加至保持空间中  

g       #从保持空间取出数据覆盖至模式空间  

G       #从保持空间取出内容追加至模式空间  

x       #把模式空间中的内容与保持空间中的内容进行互换  

n       #读取匹配到的行的下一行覆盖至模式空间  

N       #读取匹配到的行的下一行追加至模式空间  

d       #删除模式空间中的行  

D       #如果模式空间包含换行符,则删除直到第一个换行符的模式空间中的文本,并不会读取新的输入行,而使用合成的模式空间重新启动循环。如果模式空间不包含换行符,则会像发出d命令那样启动正常的新循环
 sed -n 'n;p' FILE     #-n是不在屏幕输出,n读取匹配到的行的下一行覆盖至模式空间,p将匹配结果打印。效果为输入偶数行

 seq 10 | sed 'N;s/\n//'   #N读取匹配到的行的下一行追加至模式空间,后面就是替换,将换行符替换为空。效果为将输出结果每两行合并为一行进行输出

 sed '1!G;h;$!d' FILE
 seq 10 | sed -n '/3/{g;1!p;};h'  #前一行
 seq 10 | sed -nr '/3/{n;p}'   #后一行
 sed  'N;D'FILE
 seq 10 |sed  '3h;9G;9!d'
 sed '$!N;$!D' FILE
 sed '$!d' FILE
 sed 'G' FILE
 sed 'g' FILE
 sed '/^$/d;G' FILE
 sed 'n;d' FILE
 sed -n '1!G;h;$p' FILE


2.3.3. 练习

打印偶数行

seq 10 | sed -n 'n;p'

seq 10 | sed -n '2~2p'

seq 10 | sed '1~2d'

seq 10 | sed -n '1~2!p'

2.4. 练习

2.4.1. 删除centos7系统/etc/grub2.cfg文件中所有以空白开头的行行首的空白字符

cat /etc/grub2.cfg | sed '/^$/d'

2.4.2. 删除/etc/fstab文件中所有以#开头,后面至少跟一个空白字符的行的行首的#和空白字符

cat /etc/fstab | sed -En 's/^# //p'

2.4.3. 在/etc/fstab文件中不以#开头的行的行首增加#号

cat /etc/fstab | sed -En 's@^([^#].*$)@# \1@p'

2.4.4. 处理/etc/fstab路径,使用sed命令取出其目录名和基名(这个路径太简单了,就随便写了个三级路径)

目录名:echo /etc/hha/lala | sed -En 's@(/.*)+/(.*)@\1@p'

基名:echo /etc/hha/lala | sed -En 's@(/.*)+/(.*)@\2@p'

2.4.5. 利用sed 取出ifconfig命令中本机的IPv4地址

ifconfig | sed -En '2s@^.*inet @@p' | sed -En 's@net.*$@@p'

2.4.6. 统计/etc/init.d/functions文件中每个单词的出现次数,并排序(用grep和sed两种方法分别实现)

grep -o "\([[:alpha:]][[:alpha:]]\+\)" /etc/init.d/functions | sort | uniq -c 

sed 's@ @\n@g' /etc/init.d/functions | sort | uniq -c

sed 's/\t/\n/g;s/ /\n/g' /etc/init.d/functions |sort |uniq -c

sed 's/[^a-zA-Z]/\n/g' /etc/init.d/functions |sort |uniq -c

2.4.7. 将文本文件的n和n+1行合并为一行,n为奇数行

sed -n 'N;s@\n@@p' haha

3. 文本处理三剑客之 awk

3.1. awk工作原理和基本用法说明

3.1.1. 报告生成器,格式化文本输出,GNU/Linux发布的AWK目前由自由软件基金会(FSF)进行开发和维护,通常也称它为 GNU AWK

3.1.2. gawk:

模式扫描和处理语言,可以实现下面功能 文本处理 输出格式化的文本报表 执行算数运算 执行字符串操作

3.1.3. 格式:

awk [options]  'program' var=value  file…  awk [options]  -f programfile  var=value file…

3.1.4. 说明:

program通常是被放在单引号中,并可以由三种部分组成 BEGIN语句块 模式匹配的通用语句块 END语句块

3.1.5. 选项:

-F “分隔符” 指明输入时用到的字段分隔符,默认的分隔符是若干个连续空白符  -v var=value 变量赋值

3.1.6. Program格式:

pattern{action statements;..}

3.1.7. 分割符、域和记录:

由分隔符分隔的字段(列column,域field)标记$1,$2…$n称为域标识,$0为所有域,注意:和shell中变量$符含义不同 文件的每一行称为记录record 如果省略action,则默认执行 print $0 的操作

3.2. 动作 print

3.2.1. 格式:

print item1, item2, ...

3.2.2. 说明:

逗号分隔符 输出item可以字符串,也可是数值;当前记录的字段、变量或awk的表达式 如省略item,相当于print $0 固定字符符需要用“ ” 引起来,而变量和数字不需要

3.2.3. 面试题:

取出网站访问量最大的前3个IP

awk '{print $1}' nginx.access.log-20200428|sort |uniq -c |sort -nr|head -3

awk '{print $1}' access_log |sort |uniq -c|sort -nr|head

取出分区利用率

df | awk '{print $1,$5}'

df | awk -F"[[:space:]]+|%" '{print $5}'

df | grep "^/dev/sd" | awk -F"[[:space:]]+|%" '{print $5}'

df | grep '^/dev/sd'| awk -F'[[:space:]]+|%' '{print $1,$5}' 

取nginx的访问日志的中IP和时间

取出日志文件中的前五行作为展示

awk -F'[[ ]' '{print $1,$5}' test 
#以空格和[作为分隔符输出第一项和第五项,即ip与时间

取 ifconfig 输出结果中的IP地址

ifconfig ens33 | awk '/netmask/{print $2}'

ifconfig | sed -n '2p' | awk -F' ' '{print$2}'

3.3. awk变量

3.3.1. awk中的变量分为:内置和自定义变量

3.3.2. 常见的内置变量

FS:输入字段分隔符,默认为空白字符,功能相当于 -F

awk -v FS=":" '{print $1FS$3}' /etc/passwd |head -n3
S=:;awk -F$S '{print $1,$3}' /etc/passwd|head -n3
#注意:
 -F 和 FS变量功能一样,同时使用会冲突
 -F 和 FS变量功能一样,同时使用会 -F 优先级高

OFS:输出字段分隔符,默认为空白字符

awk -v FS=':' -v OFS='@' '{print $1,$3,$7}' 

RS:输入记录record分隔符(awk是一行一行输入的,所以输入记录分隔符就是换行符),指定输入时的换行符,默认为换行符“\n”

awk -v RS=' ' '{print }' /etc/passwd

ORS:输出记录分隔符,输出时用指定符号代替换行符

awk -v RS=' ' -v ORS='###'  '{print $0}' /etc/passwd

NF:字段数量

awk -F:'{print $(NF-1)}' /etc/passwd

面试题:

连接数最多的前3个IP

awk -F" +|:" '{print $(NF-2)}' ss.log |sort |uniq -c|sort -nr|head -n3

awk -F" +|:" '/^ESTAB/{print $(NF-2)}' ss.log |sort |uniq -c|sort -nr|head -n3

ss -nt |grep "^ESTAB" | awk -F"[[:space:]]+|:" '{print $(NF-2)}'

ss -nt |awk -F"[[:space:]]+|:" '/^ESTAB/{print $(NF-2)}'

ss -nt|awk -F: '{print $(NF-1)}' |awk '/^[0-9]/{print $NF}'|sort |uniq -c |head -n 3

awk -F' +|:' 'NR!=1{print $(NF-2)}' ss.log|sort |uniq -c

每十分钟检查将连接数超过100个以上的IP放入黑名单拒绝访问

NR:记录的编号

#取ifconfig输出结果中的IP地址
ifconfig eth0 | awk 'NR==2{print $2}'

#尝试一下有趣的现象:
awk -F: '{print NR}' /etc/passwd
awk -F: 'END{print NR}' /etc/passwd
awk -F: 'BEGIN{print NR}' /etc/passwd 
#为什么会从0开始

FNR:各文件分别计数,记录的编号

awk '{print FNR,$0}' /etc/issue /etc/redhat-release   

NR与FNR的现象对比

FILENAME:当前文件名

awk '{print FNR,FILENAME,$0}' /etc/issue /etc/redhat-release 

ARGC:命令行参数的个数

awk '{print ARGC}' /etc/issue /etc/redhat-release 

ARGV:数组,保存的是命令行所给定的各参数,每一个参数:ARGV[0],……

awk 'BEGIN{print ARGC ARGV[1]}' /etc/issue /etc/redhat-release  

ARGC为3
 分别是 
 ARGV[0]:awk 
 ARGV[1]:/etc/issue
 ARGV[2]:/etc/redhat-release

3.3.3. 自定义变量

自定义变量是区分字符大小写的,使用下面方式进行赋值
-v var=value
在program中直接定义

变量的赋值如果在外面写的话不能串着写,在内部可以串着写

3.4. 动作printf

3.4.1. printf 可以实现格式化输出

3.4.2. 格式:

printf “FORMAT”, item1, item2, ...

3.4.3. 说明:

必须指定FORMAT 不会自动换行,需要显式给出换行控制符 \n FORMAT中需要分别为后面每个item指定格式符

3.4.4. 格式符:与item一一对应

 %s:        #显示字符串
 %d, %i:    #显示十进制整数
 %f:        #显示为浮点数
 %e, %E:    #显示科学计数法数值
 %c:        #显示字符的ASCII码
 %g, %G:    #以科学计数法或浮点形式显示数值
 %u:        #无符号整数
 %%:        #显示%自身

3.4.5. 修饰符

#[.#]      #第一个数字控制显示的宽度;第二个#表示小数点后精度,如:%3.1f
-           #左对齐(默认右对齐) 如:%-15s(左对齐显示字符串宽度为15个字节)
+           #显示数值的正负符号  如:%+d

3.4.6. 举例

awk -F: ‘{printf “%-20s %-10d\n”,$1,$3}’ /etc/passwd

输出/etc/passwd文件中的第一列和第三列,第一列输出字符串宽度为20左对齐,第三列输出数字穿度为10左对齐,然后换行。(所以第三列的百分号不会输出)

3.5. 操作符

3.5.1. 算术操作符:

x+y, x-y, x*y, x/y, x^y, x%y
 -x:转换为负数
 +x:将字符串转换为数值

3.5.2. 字符串操作符:没有符号的操作符,字符串连接

3.5.3. 赋值操作符:

=, +=, -=, *=, /=, %=, ^=,++, --

+在后面,所以先输出i=0,然后在i=i+1,然后i=1,再输出i=1

因为没有定义i的初始值,所以i从0开始,但是i为0的时候为假,所以此时没有输出,当进行了一次+1运算后,i为1此时为真,就会进行输出,所以会从第二行还是输出

!为取反,所以只有当n为0的时候,取反才为真,才会有输出。所以只会输出第一行的内容

3.5.4. 比较操作符:

==, !=, >, >=, <, <=
awk -F: '$3>=1000' /etc/passwd      #查看uid大于1000的用户信息

awk 'NR==2' /etc/issue

seq 10 | awk 'NR%2==0'              #取偶数,记录值除2余数为零

seq 10 | awk 'NR%2==1'              #取基数,记录值除2余数为一

seq 10 | awk 'NR%2!=0'              #取基数,记录值除2余数不为零

3.5.5. 模式匹配符:

~ 左边是否和右边匹配,包含关系
!~ 是否不匹配

awk -F: ‘$0 ~ /root/{print $1}’ /etc/passwd

将$0中含有root的行的$1输出

3.5.6. 逻辑操作符:

与:&&,并且关系
或:,或者关系
非:!,取反

3.5.7. 条件表达式(三目表达式)

selector?if-true-expression:if-false-expression

df | awk -F”[ %]+” ‘/^\/dev\//{$(NF-1)>10?disk=”full”:disk=”ok”;print $(NF-1),disk}’

selector为真,执行if-true的内容;
selector为假,执行if-false

3.6. 模式PATTERN

3.6.1. PATTERN:根据pattern条件,过滤匹配的行,再做处理

如果未指定:空模式,匹配每一行

/regular expression/:仅处理能够模式匹配到的行,需要用/ /括起来

relational expression: 关系表达式,结果为“真”才会被处理
真:结果为非0值,非空字符串
假:结果为空字符串或0值

line ranges:行范围
不支持直接用行号,但可以使用变量NR间接指定行号
/pat1/,/pat2/ 不支持直接给出数字格式

取出以b开头到以s开头的范围内的内容

BEGIN/END模式
BEGIN{}:仅在开始处理文件中的文本之前执行一次
END{}:仅在文本处理完成之后执行一次

制作一个简单的表格

awk -F: 'BEGIN{printf "--------------------------------\n%-20s|%-10s|\n--------------------------------\n","Username","Uid"} {printf "n%-20s|%-10d|\n--------------------------------\n",$1,$3}' /etc/passwd

3.7. 条件判断if-else

3.7.1. 语法

if(condition){statement;…}[else statement]
if(condition1){statement1}else if(condition2){statement2}else if(condition3){statement3}…… else {statementN}

3.7.2. 使用场景:对awk取得的整行或某个字段做条件判断

3.8. 条件判断switch

3.8.1. 语法

switch(expression) {case VALUE1 or /REGEXP/: statement1; case VALUE2 or
/REGEXP2/: statement2; …; default: statementn}

3.9. 循环while

3.9.1. 语法

while (condition) {statement;…}

3.9.2. 条件“真”,进入循环;条件“假”,退出循环

3.9.3. 使用场景: 对一行内的多个字段逐一类似处理时使用 对数组中的各元素逐一处理时使用

3.10. 循环do-while

3.10.1. 语法

do {statement;…}while(condition)

3.10.2. 意义:无论真假,至少执行一次循环体

3.11. 循环for

3.11.1. 语法

for(expr1;expr2;expr3) {statement;…}

3.11.2. 常见用法

for(variable assignment;condition;iteration process) {for-body}

3.11.3. 特殊用法:能够遍历数组中的元素

for(var in array) {for-body}

3.12. continue 和 break

3.12.1. continue 中断本次循环

格式:continue [n]

3.12.2. break 中断整个循环

格式:break [n]

3.13. next

3.13.1. 可以提前结束对本行处理而直接进入下一行处理(awk自身循环)

3.14. 数组

3.14.1. awk的数组为关联数组

3.14.2. 格式:

array_name[index-expression]

index-expression

利用数组,实现 k/v 功能
可使用任意字符串;字符串要使用双引号括起来
如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”
若要判断数组中是否存在某元素,要使用“index in array”格式进行遍历

3.14.3. 面试题:统计服务器的链接状态

·

·

3.15. awk 函数

3.15.1. 分为内置和自定义函数

3.15.2. 常见内置函数

数值处理

rand():返回0和1之间一个随机数
srand():配合rand() 函数,生成随机数的种子
int():返回整数

字符串处理

length([s]):返回指定字符串的长度
sub(r,s,[t]):对t字符串搜索r表示模式匹配的内容,并将第一个匹配内容替换为s
gsub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并全部替换为s所表示的内容
split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组中,第一个索引值为1,第二个索引值为2,…

调用shell命令

system(‘cmd’)

空格是awk中的字符串连接符,如果system中需要使用awk中的变量可以使用空格分隔,或者说除了awk的变量外其他一律用””引用起来

时间函数

systime() 当前时间到1970年1月1日的秒数
strftime() 指定时间格式

3.15.3. 自定义函数

格式

function name ( parameter, parameter, ... ) {
     statements
     return expression
 }

3.16. awk 脚本

3.16.1. 将awk程序写成脚本,直接调用或执行

3.16.2. 向awk脚本传递参数

格式:awkfile  var=value  var2=value2... Inputfile

3.16.3. 注意:

在BEGIN过程中不可用。直到首行输入完成以后,变量才可用。可以通过-v 参数,让awk在执行BEGIN之前得到变量的值。命令行中每一个指定的变量都需要一个-v参数

4. 练习

4.1. 文件host_list.log 如下格式,请提取”.magedu.com”前面的主机名部分并写入到回到该文件中

4.2. 统计/etc/fstab文件中每个文件系统类型出现的次数

4.3. 统计/etc/fstab文件中每个单词出现的次数

4.4. 提取出字符串Yd$C@M05MB%9&Bdh7dq+YVixp3vpw中的所有数字

4.5. 有一文件记录了1-100000之间随机的整数共5000个,存储的格式100,50,35,89…请取出其中最大和最小的整数

4.6. 解决Dos攻击生产案例:根据web日志或者或者网络连接数,监控当某个IP并发连接数或者短时内PV达到100,即调用防火墙命令封掉对应的IP,监控频率每隔5分钟。防火墙命令为:iptables -AINPUT -s IP -j REJECT

4.7. 将以下文件内容中FQDN取出并根据其进行计数从高到低排序

4.8. 将以下文本文件awktest.txt中 以inode列为标记,对inode列相同的counts列进行累加,并且统计出同一inode中,beginnumber列中的最小值和endnumber列中的最大值