linux命令-文本处理-2-11
大纲
| 命令 | 主要功能 | 应用场景 |
|---|---|---|
find | 文件查找 | 查找特定文件、批量处理文件 |
awk | 复杂文本分析与处理 | 按条件提取数据、计算平均值 |
find
find 查找路径 查找标准 查找到以后的处理运作,实时、 精确、遍历指定目录中所有文件完成查找、速度慢。
-
查找路径
- 查找路径:默认为当前目录
- 查找标准:默认为指定路径下的所有文件
- 处理运作:默认为显示
- 查找标准,匹配标准
-
参数
参数类型 关键参数 功能说明 按名称查找 -name pattern按文件名匹配(区分大小写,支持 *通配符)-iname pattern对文件名匹配时不区分大小写 按文件类型 -type f/d/l匹配普通文件(f)、目录(d)、符号链接(l)等 按大小查找 -size +n/-n [kMG]查找大于(+)或小于(-)n 单位的文件(k=KB,M=MB,G=GB) 组合条件 -a与, -o或,-not非 按时间查找 -mtime +n/-n按内容修改时间(n 天内/前)查找 -mmin +n/-n按内容修改时间(n 分钟内/前)查找 执行动作 -exec command {} \;对匹配文件执行 command( {}替换为文件名,\;结束命令)-print打印匹配文件路径(默认动作) -
-iname pattern匹配符 说明 * 星号 匹配任意长度的任意字符 ? 问号 匹配任意单个字符 [] 中括号 匹配指定范围内的任意单个字符 -
最后查询参数
属性 说明 -print 显示 -ls 类似ls -l的形式显示每一个文件的详细信息 -ok command {}; 一定要有;结束 {}花括号表示找到的文件 每一次操作都需要用户确认 -exec command {}; 每一次操作都不需要用户确认 xargs 从标准输入接收到并且执行 -delete 删除查找的文件,先查出在使用-delete 慎之又慎
-
-
示例
-
当前目录查找
.txt文件[root@localhost opt]# find . -name *.txt find: 路径必须在表达式之前: a.txt 用法: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression][root@localhost opt]# find . -name "*.txt" 带上双引号 ./regular_express.txt[root@localhost opt]# find -iname "*.txt" <-- 忽略大小写 -
查找
/var/log下大于 100MB 的普通文件[root@localhost opt]# find /var/log -type f -size +1M -exec ls -lh {} \; -rw-------. 1 root root 1.2M 11月 2 11:32 /var/log/messages -rw-------. 1 root root 1.6M 10月 8 09:10 /var/log/anaconda/journal.log -
查找当前目录下小于 1KB 的空文件
[root@localhost opt]# find /var/log -type f -size -1M -exec ls -lh {} \; -rw-------. 1 root root 0 10月 8 09:08 /var/log/tallylog -rw-------. 1 root root 0 10月 8 09:08 /var/log/spooler -
查找最近 7 天修改过的配置文件
[root@localhost opt]# find /etc -name "*.conf" -mtime +7 -exec ls -lh {} \; -rw-r-----. 1 root root 191 6月 20 2018 /etc/libaudit.conf -rw-r--r--. 1 root root 1.7K 12月 7 2011 /etc/security/pwquality.conf[root@localhost opt]# stat /etc/libaudit.conf 最近改动:2025-10-08 09:07:59.186981492 +0800[root@localhost opt]# stat /etc/security/pwquality.conf 最近改动:2025-10-08 09:08:00.371981409 +0800 -
删除 30 天前的
.tmp临时文件find /tmp -name "*.tmp" -mtime +30 -exec rm -f {} \; -
查找权限为 777 的文件
find / -perm 777 -type f
-
awk
awk语法
-
选项
参数/变量 作用 示例 -F fs指定输入字段分隔符 awk -F ',' '{print $1}' data.csv(逗号分隔,取第一列)-v var=val定义自定义变量 awk -va=1 '{print $1 + a}' file($1 加 1 输出)-f script从文件加载脚本 awk -f script.awk data.txt(执行脚本文件)$0当前行全部内容 awk '{print $0}' file(打印全行)$n第 n 个字段 awk '{print $2, $3}' file(打印第二、三列)NF当前行字段总数 awk '{print NF}' file(输出每行字段数)NR当前处理行号 awk '{print NR, $0}' file(行号+内容) -
基本用法
-
awk [options] ‘program’ var=value file…
-
awk [options] -f program file var=value file…
-
awk [options] ‘BEGIN{action;… }pattern{action;… }END{action;… }’ file …
-
awk 程序可由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块,共3部分组成
-
program 通常是被放在单引号中, 选项:
Program:pattern{action statements;..}说明 事件参数 pattern部分决定动作语句何时触发及触发事件 BEGIN,END action statements对数据进行处理,放在{}内指明 print, printf -
分割符、域和记录
- awk执行时,由分隔符分隔的字段(域)标记$1,$2…$n称为域标识。$0为所有域,注意:此时和shell中变量$符含义不同
-
awk工作原理
- 第一步:执行BEGIN{action;… }语句块中的语句
- 第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ action;… }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。逐行读取并过滤
- 第三步:当读至输入流末尾时,执行END{action;…}语句块
- BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中
- END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块
- pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块
awk表达式
-
模式匹配表达式: BEGIN\END
-
BEGIN :让用户指定在第一条输入记录被处理之前所发生的动作,通常可在这里设置全局变量。
-
END :让用户在最后一条输入记录被读取之后发生的动作。
-
示例
# 使用BEGIN可直接输出打印结果 ~]# awk 'BEGIN{print 1+1}' # 结果: 2 ~]# awk 'BEGIN{print "line 1\nline 2"}' # line 1 \n line 2# 头部展示为USER USERID, 结尾为END FILE [root@localhost opt]# awk -F: 'BEGIN{print "USER USERID"}{print $1":"$3}END{print "END FILE"}' passwd USER USERID root:0 bin:1 daemon:2 adm:3 ... END FILE
-
-
awk内置变量
-
参数
字段 说明 ARGC 命令行参数个数 ARGY 命令行参数排列 ENVIRON 支持队列中系统环境变量的使用 FILENAME awk 浏览的文件名, 在命令中获取当前文件名 NF 表示当前记录的字段个数 NR 表示当前记录编号等, 如果有多个文件,这个数目会把处理的多个文件中行统一计数 FNR 浏览文件的记录数,与 NR 不同的是, FNR 用于记录正处理的行是当前这一文件中被总共处理的行数 FS field separator, 设置输入域分隔符,等价于命令行,-F 选项 RS Record separator, 输入数据的记录分隔符 OFS Output Filed Separator, 输出数据的字段分割符 ORS 输出数据的记录分隔符, $n $0 变量是指整条记录, $1 表示当前行的第一个域, $2 表示当前行的第二个域,··· -
示例
-
内置变量:
FS, OFS $n# BEGIN{FS=":"} 等于 -F: # BEGIN{FS=":";OFS=","}/要查找的字符串/{print $1,$NF} [root@localhost opt]# awk 'BEGIN{FS=":";OFS=","}/root/{print $1,$NF}' passwd root,/bin/bash <-- # 如果 OFS=":" 那就是 root:x operator,/sbin/nologin OFS="," <-- 就是在$1,$NF 中间加上, -
内置变量:
FILENAME# nologin是要查找的值 [root@localhost opt]# awk 'BEGIN{FS=":";OFS=","}/root/{print $1,"filename:" FILENAME}' /etc/passwd root,filename:/etc/passwd --> "filename:" FILENAME, 第一个直接打印 operator,filename:/etc/passwd --> 第二个是内置变量# 这里是直接打印全部的值 ~]# awk -F: '{print $1,"filename: ",FILENAME}' /etc/passwdroot filename: /etc/passwd -
内置变量:
ENVIRON["PATH"], FNR[root@localhost opt]# awk 'BEGIN{print ENVIRO['path']}/root/{print $1,$2}' passwd wwwwww root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin # 查找env中PATH有的路径~]# awk 'BEGIN{print ENVIRON["PATH"]}/root/{print FNR"@"$0}' /etc/passwd # BEGIN{print ENVIRON["PATH"]}/usr/local/sbin:/usr/local/bin:/usr/sbin:/zzzzzzz# /root/{print FNR"@"$0}, # /root/: 先查找带root的行# FNR: 操作的行数,@: 分割, $0: 显示全部1@root:x:0:0:root:/root:/bin/bash10@operator:x:11:0:operator:/root:/sbin/nologin# 如果做为两段,那就是匹配全部~]# awk 'BEGIN{print ENVIRON["PATH"]}''{print FNR"@"$0}' /etc/passwd
-
-
-
action输出
参数 参数 说明 print 变量、数值或字符串 符串必须用双引号引用,参数用逗号分隔,如果没有逗号,参数就串联在一起,无法区分,在这逗号的作用与输出文件的分隔符作用是一样的,只是后者是空格而已 printf 格式化字符串 输出复杂时,printf 的结果更加人性化 -
参数-print
-
说明
- 各项目之间使用逗号隔开,而输出时则以空白字符分隔;
- 输出的 item 可以为字符串或数值、当前记录的字段 ( 如 $1) 、变量或 awk 的表达式;数值会先转换为字符串,而后再输出
- print 命令后面的 item 可以省略,此时其功能相当于 print $0, 如果想输出空白行,则需要使用 print “”
-
示例
-
分割: 显示$1 $3列
[root@localhost opt]# awk -F":" '{print $1,":",$3}' passwd root : 0 bin : 1 -
如果不写相当于$0, 匹配全部
[root@localhost opt]# awk -F":" '{print }' passwd --> 两个等值 [root@localhost opt]# awk -F":" '{print $0}' passwd -
如有10行 就打印10行的空白行
awk -F: '{print ""}' /etc/passwd
-
-
-
参数-printf
使用格式:
printf format, item1, item2, ...-
选项 --> format 格式的指示符都以 % 开头,后跟一个字符;如下
字段 说明 %c 显示字符的 ASCII 码 %d, %i 十进制整数 %e, %E 科学计数法显示数值 %f 显示浮点数 %g, %G 以科学计数法的格式或浮点数的格式显示数值 %s 显示字符串,如 -F: '{printf "%-10s %s\n",$1,$7}' passwd%u 无符号整数 %% 显示 % 自身 -
修饰符
字段 说明 N 显示宽度 - 左对齐(默认右对齐) %-15s + 显示数值符号 %+d -
要点说明
- 与 print 命令的最大不同是, printf 需要指定 format
- format 用于指定后面的每个 item 的输出格式
- printf 语句不会自动打印换行符; \n
-
示例-1
[root@localhost opt]# awk -F: '{printf "%-20s %d\n",$1,$NF}' passwd # $1 对应 %-20s $NF 对应 %d # 每个 输出的域都必须对应一个format选项 \n需要手动指定否则不会换行 root 0 bin 1 daemon 2 ... -
示例-2
[root@localhost opt]# awk -F: '{printf "username: %-15s bash: %s\n",$1,$NF}' passwd # $1 对应 username: %-15s $NF 对应 bash: %s username: root bash: /bin/bash username: bin bash: /sbin/nologin username: daemon bash: /sbin/nologin username: adm bash: /sbin/nologin ...
-
-
-
条件表达式
三目表达式(重要): selector?if-true-expression:if-false-expression 类似于if else, [太复杂了,不如多敲几个命令,生产环境要是长久不用容易忘了是啥意思]
-
示例
# 如果 $3大于等于1000, 自定义变量userType就是command User, 否则就是system User # ; 隔开 printf 打印 $1, 第2个字段就是自定义变量 [root@localhost opt]# awk -F: '{$3>=1000?userType="普通用户":userType="系统用户"; printf "用户名: %-20s,%s\n", $1,userType}' passwd 用户名: root ,系统用户 用户名: bin ,系统用户 。。。。 用户名: xiong ,普通用户 用户名: xiong2 ,普通用户# $3>=1000?userType="普通用户":userType="系统用户"; printf "用户名: %-20s,%s\n", $1,userType # $3>=1000?userType="普通用户": --> 相当于 if, 如果第三列大于1000显示普通用户 # userType="系统用户"; --> 相当于 else,小于就是系统用户 # printf "用户名: %-20s,%s\n", $1,userType # --> 用户名: %-20s=$1 %s=自定义的userType
-
-
awk循环语句
-
for
常见用法:
for(variable assignment;condition;iteration process) {for-body}
特殊用法:能够遍历数组中的元素 语法:for(var in array) {for-body}-
示例
'/匹配字段/{for(xx) {print xx}}' 注意 for的{包含print}# /^[[:space:]]*linux16/{for (i=i;i<=NF;i++){printf "列:%-25s 字 节:%s\n", $i, length($i)}} # /^[[:space:]]*linux16/ --> 查找空格linux16的行 # {for (i=i;i<=NF;i++){printf "列:%-25s 字 节:%s\n", $i, length($i)}}# --> 循环查找到这行 如下 列: linux16 /vmlinuz-3.10.0-957.el7.x86_64 root=/dev/mapper/centos-root ro rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet LANG=zh_CN.UTF-8 字节:143 列:linux16 字节:7 列:/vmlinuz-3.10.0-957.el7.x86_64 字节:30 列:root=/dev/mapper/centos-root 字节:28 列:ro 字节:2 ..
-
-
break\continue
常用于 for循环或case语句中
-
示例-continue 退出当前继续继续下一条
# BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i}print sum} # 1、{sum=0;for(i=1;i<=100;i++)print sum} # 先执行循环 # 2、{if(i%2==0)continue;sum+=i} # 在执行if ,如果是偶数让sum叠加 # 注意sum=0;这里是; 分号 命令继续执行 # {if(i%2==0)continue;sum+=i} 如果想在同一行执行就加上; ~]# awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i}print sum}' # 结果: 2500 取余为零的 叠加 偶数结果为2500 -
示例-break
~]# awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i>=66)break;sum+=i}print sum}' # 结果: 2145 当等于66时退出该脚本
-
-
awk数组
若要遍历数组中的每个元素,要使用for循环:
for(var in array) {for-body}⚠️: 如果某数据组元素事先不存在,那么在引用其时, awk 会自动创建此元素并初始化为空串;因此,要判断某数据组中是否存在某元素,需要使用 index in array 的方式
-
示例 - 定义一个数组, for循环之后打印其结果
]# awk 'BEGIN{weekdays["mon"]="Monday"; weekdays["tue"]="Tuesday";for(i in weekdays){print weekdays[i]}}' Tuesday Monday -
汇总 --> 多练,这个生产用的多
[root@localhost opt]# netstat -an | awk '/^tcp/{s[$6]++}END{for(i in s){print i,s[i]}}'# /^tcp/{s[$6]++}END{for(i in s){print i,s[i]}} # /^tcp/{s[$6]++}END{for(i in s) --> $6 这列for循环叠加,设置 s 变量 # {print i,s[i]}} 打印 i , s[i] 最后叠加的值LISTEN 4 ESTABLISHED 2 -
匹配IP地址,根据类型匹配, 此处日志格式为
{"@timestamp":"2020-01-08T15:38:53+08:00","host":"xxxxxx","clientip":"yyyyy","size":4442,"responsetime":0.883,"upstreamtime":"0.883","upstreamhost":"后端机器:8080","http_host":"xxxxxx","url":"/xx.do","domain":"xxxxxx","xff":"-","referer":"http://xxxxxx:8888/user/home.do","status":"200"} # awk 匹配 ]# awk -F',' '{print $3}' access.log | awk -F":" '{clientip[$NF]++};END{for(i in clientip)print i,clientip[i]}' | sed 's/\"//g'
-
-
