1.sed的命令解析
1.1.Stream EDitor 流式编辑器
特点:
— 非交互,基于模式匹配过滤及修改文本
— 逐行处理,并将结果输出到屏幕
— 可实现对文本的输出、删除、替换、复制、剪切、导入、导出等各种操作
1.2.sed命令解析
基本用法:
— 格式1:前置命令 | sed 选项 ‘条件指令’
— 格式2:sed 选项 ‘条件指令’ 文件…
相关说明如下:
条件可以是行号或者正则
没有条件时,默认为所有行
指令可以是增、删、改、查等指令
默认sed会将所有输出的内容都打印出来,可以使用 –n 屏蔽默认输出
选项中可以使用 –r 选项,让sed支持扩展正则
常用选项
-n 屏蔽默认输出(全部文本)
-i 直接修改文件内容
-r 启用扩展正则表达式,若与其他选项一起使用,应作为首个选项
1.3.sed的常用命令
1.4.sed命令解析/输出指令
1.输出指令
条件可以是行号或/正则
行号可以使用单个数字表示单行
或者3,5表示连续的多行
省略条件则默认逐行处理全部文件
匹配正则时,需要使用//
sed -n 'p' /etc/passwd #输出所有
sed -n '3p' /etc/passwd #输出第三行
sed -n '1,4p' /etc/passwd #输出1-4行
sed -n '4,+10p' /etc/passwd #输出第四行以及后边的10行内容
sed -n '/^root/p' /etc/passwd #输出以root开头的行
sed -n '$=' /etc/passwd #输出文件总行数
2.删除指令
删除文本 —— 指令 d
此案例中只作输出,不更改原文件,若要更改原文件应添加-i 选项
sed ‘1,3d’ 1.txt #删除第1-3行
sed ‘/acb/d’ 1.txt #删除所有包含acb的行
sed ‘/aaa/!d’ 1.txt #删除不包含aaa的行
sed ‘/^abc/d’ 1.txt #删除以abc开头的行
sed ‘KaTeX parse error: Expected 'EOF', got '#' at position 13: d’ 1.txt #̲删除文件最后一行 sed ‘/…/d’ 1.txt #删除所有空行
3.替换指令
替换文本 —— 指令 s
此案例中只作输出,不更改原文件,若要更改原文件应添加-i 选项
sed ‘s/aa/bb/’ 1.txt #将每行中的第一个aa替换为bb
sed ‘s/aa/bb/3’ 1.txt #将每行中的第三个aa替换为bb
sed ‘s/aa/bb/g’ 1.txt #将所有的aa都替换为bb
sed ‘s/aa//g’ 1.txt #将所有的aa替换为空值(相当于删除)
sed -n‘s/aa/bb/p’ 1.txt #只打印替换的内容
sed -n ‘1,7s/^/#/p’ 1.txt #批量给1-7行添加注释(s 前边可以指定行号)
sed -n ‘1,7s/^#//p 1.txt #批量给1-7行注释去掉
注意:替换操作符的分隔符 “/”可以改用其他的分隔符,如 # ,& 等,便于修改文件路径
[root@test opt]# sed -n 's#/bin/bash#/sbin/sh#p’ /etc/passwd
4.导入导出功能
基本动作
r 动作应结合 –I 选项才会存入,否则只会输出
w 动作以覆盖的方式另存为新文件
r 动作应结合 –I 选项才会存入,否则只会输出
将b.txt文件内容导入到test.txt文件里每一行的下边
[root@test opt]# sed ‘r b.txt’ test.txt
将b.txt文件内容导入到test.txt文件第2行下边
[root@test opt]# sed ‘2r b.txt’ test.txt
将b.txt文件内容导入到test.txt文件1-3行每一行的下边
[root@test opt]# sed ‘1,3r b.txt’ test.txt
w 动作以覆盖的方式另存为新文件
将b.txt文件所有内容导出另存为c.txt文件里,c.txt文件没有可自动创建
[root@test opt]# sed ‘w c.txt’ b.txt
将b.txt文件第2行内容导出另存为c.txt文件里,原有的内容将被覆盖
[root@test opt]# sed ‘2w c.txt’ b.txt
2.awk的命令解析
2.1.awk概括
awk编程语言/数据处理引擎
创造者:Aho Wwinberger Kernighan
基于模式匹配检查输入文本,逐行处理并输出
通常用在shell中,获取指定的数据
单独使用时,可对文本数据做统计
2.2.awk命令格式
主要用法
格式1:前置命令 | awk 选项 ‘条件{指令}’
格式2:awk 选项 ‘条件{指令}’文件… …
其中print是最常用的编辑指令,若有多条指令用分号 ;分隔
awk过滤数据时支持仅打印某一列,如第2列、第4列等
处理文件时,若未指定分隔符,则默认将空格、制表符(tab键)等作为分隔符
[root@test ~]# df -h | awk '{print $4}’
[root@test ~]# awk ‘{print $1,$4}’ 文件
常用命令选项
-F 指定分隔符,如不指定分隔符默认以空格或tab为默认分隔符
示例:过滤passwd文件中以分号为分隔符,打印第1列,第3列
[root@test ~]# awk -F: ‘{print $1,$3}’ /etc/passwd
root 0
bin 1
daemon 2
… …
[root@test opt]# awk -F: ‘{print $1,$7}’ /etc/passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
… …
通过awk检查内存的剩余容量
[root@test ~]# free | awk '/Mem/ {print $4}’
通过awk过滤网卡入口流量
[root@test ~]# ifconfig ens160 | awk '/RX p/ {print $5}’
通过awk过滤网卡出口流量
[root@test ~]# ifconfig ens160 | awk ‘/TX p/{print $5}’
awk还识别多种单个的字符,比如以“:”或“/”分隔
指定多个分隔符:以“:”或“/”为分隔符,打印用户名字段,解释器字段
[root@test ~]# head -1 /etc/passwd
root❌0:0:root:/root:/bin/bash
[root@test ~]# awk -F[😕] ‘{print $1,$10}’ /etc/passwd
root bash
bin nologin
daemon nologin
adm sbin
… …
2.3.awk内置变量
awk内置变量
$1 文件第一列
$2 文件第二列
$3 文件第三列,依此类推
NR 文件当前的行号
NF 文件当前行的列数
以 “:”为分隔,输出文件每一行的行号、列数
[root@test ~]# awk -F: ‘{print NR,NF}’ /etc/passwd
1 7
2 7
… …
[root@test ~]# awk -F: ‘{print $1,“用户的解释器为”,$7}’ /etc/passwd
练习1:
利用awk过滤网卡流量信息
#!/bin/bash
while :
do
clear
ifconfig ens160 | awk ‘/inet /{print $2}’ #打印网卡ip列数
ifconfig ens160 | awk ‘/RX p/{print $5}’ #打印网卡入口流量列数
ifconfig ens160 | awk ‘/TX p/{print KaTeX parse error: Expected 'EOF', got '}' at position 2: 5}̲’ #打印网卡出口流量列数 s…/{print “根分区剩余:”,$4}’
free -h | awk ‘/Mem/{print “内存剩余:”,$4}’
2.3.awk过滤时机
awk会逐行处理文本,支持在处理第一行之前做一些准备工作,以及处理完最后一行之后做一些总结性质的工作
awk 选项 ‘BEGIN{指令} {指令} END{指令}’ 文件
— BEGIN{} 行前处理,读取文件内容前执行,指令执行1此
— {} 逐行处理,读取文件过程中执行,指令执行n次
— END{} 行后处理,读取文件结束后执行,指令执行1次
练习3:
只做预处理时,可以没有操作的文件
打印常量
[root@test ~]# awk ‘BEGIN{print “正在处理中”}’
正在处理中
打印变量
[root@test ~]# awk 'BEGIN{x=10;print x}’
10
[root@test ~]# awk ‘BEGIN{x=10; print x+5}’
15
练习4:
通过awk统计系统中使用bash作为登录shell的用户总个数
实现思路:
- 预处理时赋值变量x=0
- 逐行读入passwd文件,如果发现登录shell是bash结尾则x加1
- 全部处理完毕后,输出x的值
awk ‘BEGIN{x=0}/bash$/{x++}END{print x}’ /etc/passwd
练习5:
输出以root开头的行
[root@test ~]# awk -F: ‘/^root/ {print}’ /etc/passwd
root❌0:0:root:/root:/bin/bash
[root@test ~]# awk -F: ‘/^root/’ /etc/passwd #默认为打印
root❌0:0:root:/root:/bin/bash
[root@test ~]# awk -F: ‘$1~/root/’ /etc/passwd #$1代表第一列,~ 代表匹配
root❌0:0:root:/root:/bin/bash
练习6:
找出passwd文件中解释器不是以nologin结尾的行,打印用户名字段,解释器字段
解释:对第7个字段做 !~反向匹配
[root@test ~]# awk -F: ‘$7!~/nologin/{print $1,$7}’ /etc/passwd
练习8:
输出root或adm账户的用户名和解释器字段
[root@test ~]# awk -F: ‘/^(root|adm)/{print $1,$7}’ /etc/passwd
root /bin/bash
adm /sbin/nologin
2.4.数值比较
使用数值/字符串比较设置条件
比较符号:
等于 ==
不等于 !=
大于 >
大于等于 >=
小于 <
小于等于 <=
练习9:
输出第三行的用户名字段,解释器字段
[root@test ~]# awk -F: ‘NR==3{print $1,$7}’ /etc/passwd
练习10:
输出用户UID大于等于1000的用户名、UID、解释器字段
[root@test ~]# awk -F: ‘$3>=1000 {print $1,$3,$7}’ /etc/passwd
nobody 65534 /sbin/nologin
lisi 1000 /bin/bash
练习11:
输出UID小于10的用户名、UID、解释器字段
[root@test ~]# awk -F: ‘$3<10 {print $1,$3,$7}’ /etc/passwd
root 0 /bin/bash
bin 1 /sbin/nologin
练习12:
输出用户名为 “root”的行
[root@test ~]# awk -F: ‘$1==“root” {print}’ /etc/passwd
root❌0:0:root:/root:/bin/bash
练习13:
输出用户名不是“root”的行
[root@test ~]# awk -F: ‘$1 !=“root”{print}’ /etc/passwd
练习14:
逻辑条件测试
输出账户UID大于10并且小于20的账户信息,打印用户名、UID、解释器
[root@test ~]# awk -F: ‘$3>10 && $3<20 {print $1,$3,$7}’ /etc/passwd
operator 11 /sbin/nologin
games 12 /sbin/nologin
练习15:
输出账户UID大于1000或者小于10的账户信息
[root@test ~]# awk -F: ‘$3>1000 || $3<10’ /etc/passwd
2.5.awk分支结构
if 单分支: if(条件){编辑指令}
if双分支:if(条件){编辑指令1}else{编辑指令2}
if单分支统计passwd文件中UID大于或等于1000的用户个数
[root@test ~]# awk -F: ‘{if($3>=1000) {i++}} END{print i}’ /etc/passwd
24
if双分支统计passwd文件中UID大于等于1000的用户,和小于1000的用户个数
[root@test ~]# awk -F: '{if($3>=1000) {x++}else{i++}} END{print x,i} ’ /etc/passwd
24 43
2.6.awk数组
awk数组的语法格式
数组是一个数组可以存储多个值,具体使用格式如下:
定义数组的格式:数组名[下标]=元素值
调用数组的格式:数组名[下标]
数组的用法:for(变量名 in 数组名){print 数组名[变量]}
[root@test ~]# awk ‘BEGIN{x[0]=10;x[1]=20;print x[0],x[1]}’
10 20
[root@test ~]# awk ‘BEGIN{x[0]++;print x[0]}’
1
2.7.awk循环结构
awk利用for循环遍历数组的用法
— 格式:for(变量名 in 数组名){print 数组名[变量]}
[root@test ~]# awk ‘BEGIN{a[0]=00;a[1]=11;a[2]=22;for(i in a){print i,a[i]}}’
0 0
1 11
2 22
通过awk统计用户登录系统的次数
[root@test ~]# who | awk ‘{ip[$1]++}END{for(i in ip)print i,ip[i]}’