一、 sed 管道命令
sed(Stream Editor)字符流编辑器,简称流编辑器。是一种用于编辑、过滤和转换文本内容的流编辑器,可以对文本文件进行快速增删改查等操作。
1、sed 基础知识
1.1、sed 工作流程
* sed处理文本时以行为单位
* 把当前处理的行复制存储到称为模式空间的临时缓冲区中
* 接着用sed命令处理缓冲区中的内容
* 处理完成后,把缓冲区的内容送往屏幕。此时模式空间清空
* 接着处理下一行,这样不断重复,直到文件末尾
* 若是指定了需要处理的行的地址,sed操作将会逐行处理指定行
* 若是没指定需要处理的行,sed操作将会逐行处理所有的行
1.2、sed 命令语法
* sed [选项] [sed-commands] [input-file]
* sed-commands:既可以是单个sed命令,也可以是多个sed命令组合
* input-file:可选项,sed还可以从标准输出如管道获取输入
1.3、sed 匹配范围
* 空地址: 全文处理,不指定具体行
* 单地址: 指定文件某一行
* /pattern/: 被模式匹配到的每一行
* 范围区间: 10,20表示10-20行,10,+5 表示第10行加向下5行
* 步长: 1~2表示奇数行;2~2表示偶数行
1.4、sed 命令常用选项
* -n:禁止sed编辑器默认输出,与p命令一起使用完成输出。不加-n没匹配到的也会输出
* -e:表示用指定命令来处理输入的文本文件,只有一个操作命令时可省略,在执行多个操作命令使用;可使用多个-e或者使用一个-e将后面命令合并
* -i:直接修改源文本文件
* -i.bak:修改时同时创建.bak文件
* -r,-E:使用扩展正则表达式
* -f:表示用指定命令的脚本文件,来处理输入的文本文件
* -s:将多个文件视为独立文件,而不是单个连续的长文件流
* -h:显示帮助。
1.5、sed 常用内置命令
* s:替换指定字符(替换)
* d:删除指定的行(删除)
* a:在指定的行下一行增加一行指定内容(增加)
* i:在指定的行上一行插入一行指定内容(插入)
* c:将选定行内容修改为指定内容(修改)
* r:用于将内容读入文件
* w:用于将匹配内容写入到文件
* p:打印,若同时指定行,则打印指定行,若不指定行,则打印所有内容;通常与-n选项一起使用,不加-n会输出两次(默认输出一次,p输出一次)
* y:字符转换,转换之后的字符长度必须相同
* =:打印行号
* l:打印数据流中的文本和不可打印的ASCII字符
1.6、常用标记flags
* g:表示要替换所有匹配的行
* n:1-512,表示指定要替换的字符串出现第几次时才进行替换
* w file:将替换后的结果保存到指定的file文件中
* &:用正则表达式匹配的内容进行替换
* \n:匹配第n个子串,'s/括号正则,可有多个/替换后的字符串\n/p',保留前面第几个括号里匹配的,这里就写\几
* \:转义
2、sed 增删改查
2.1、sed 命令查看
# 统计行号
sed -n '$=' a.txt
# 查看文本全部内容
sed '' /etc/shadow
sed -n 'p' /etc/shadow
# 查看文本中的空行
sed -n '/^$/p' test.txt
# 查看文本中的非空行
sed -n '/^$/!p' test.txt
# 查看指定行,第1行
sed -n '1p' /etc/shadow
# 查看除过第1行之外的所有行
sed -n '1!p' /etc/shadow
# 查看3-6行的内容
sed -n '3,6p' /etc/shadow
# 查看第一行和向下5行的内容
sed -n '1,+5p' pwd.txt
# 匹配root开头的行(/模式匹配/)
sed -n '/^root/p' /etc/shadow
# 匹配含有linux的行(/模式匹配/)
sed -n '/linux/p' /etc/shadow
# 查看文件最后一行内容
sed -n '$p' /etc/shadow
# 查看icmp或者igmp开头的行
sed -rn '/^(icmp|igmp)/p' /etc/protocols
2.2、sed 命令删除
删除指定行并不是真正的删除,只是将删除了的结果显示出来,并不是真正的删除了文件中的内容,如果想要真正的删除文件中的内容需要添加选项-i
# 删除文本中的空行
sed '/^$/d' test.txt
# 删除文本中的非空行
sed '/^$/!d' test.txt
# 删除文本中的最后一行
sed '$d' test.txt
# 删除第5行到最后一行
sed '5,$d' test.txt
# 删除从root开头的行到ntp开头的行
sed '/^root/,/^ntp/d' pwd.txt
# 删除指定行
sed '2d' test.txt
# 删除含有linux的行
sed '/linux/d' a.txt
# 删除nginx.conf文件中的注释行、含有#的行、空白行
sed -r '/(^#|#|^$)/d' nginx.conf
# 删除每行前面的第一个空格
sed -r 's/^ +//g'
# 删除每行前面的所有空格
sed -r 's/^ *//g'
# 替换每一行中从第二个开始的unix
sed 's/\<unix\>/linux/2g' test.txt
# 删除第二个字符和最后一个字符
sed -r 's/(.)(.)(.*)(.)/\1\3/' g.txt
# 删除每一行最后的空白字符
sed 's/ *$//' example.txt
# 删除每行最后一个逗号
sed 's/,$//' example.txt
# 删除匹配行到最后的行
sed -i '/^abc/,$d' t1.txt
2.3、sed 命令替换
# 替换命令格式:
sed '指定需要替换的行s/需要替换的字符串/替换后的字符串/替换标记flag'
# 将替换后的结果保存到文档
sed 's/test/test1/w f.txt' b.txt
# 在第10行前面添加4个空格
sed -i "10s/^/ /" filename
# 将两位数的数字替换为number
sed -n 's/\b[0-9]\{2\}\b/number/gp' test.txt
# 将文件中的所有test替换为taget
sed -n 's/test/taget/gp' test1.txt
# 将文件中的每行第一次出现的test替换为taget
sed 's/test/taget/1p' test1.txt
# 每行第2次出现的进行替换,依次类推
sed 's/test/taget/2p' test1.txt
# 替换前10行中bin开头的,替换成C,仅显示结果
sed -ne '1,10s/^bin/C/gp' -e '1,10s/^m/M/gp' pwd.txt
sed -ne '1,10s/^bin/C/gp;1,10s/^m/M/gp' pwd.txt
# 使用脚本文件
vim zkc.txt
1,10s/^bin/C/gp
1,10s/^m/M/gp
sed -nf zkc passwd.txt
# 删除test.txt 中所有特殊字符(除了数字以及大小写字母)
sed -n 's/[^0-9a-zA-Z]//gp' passwd.txt
# 删除test.txt中5到10行中所有的数字
sed -n '5,10s/[0-9]//gp' passwd.txt
# 使用扩展正则
sed -nr '/^(root)(.*)(bash)$/p' passwd.txt
# 将文件中空格开头的行和空白行,添加注释符
sed -e 's/^[[:space:]]/#/g' -e '/^$/#/g' pwd.txt
# 找到服务器的id地址
# 去头去尾法:
ifconfig eth0 |sed -n '2p' | sed 's/^.*inet//g' | sed 's/net.*$//g'
# -e参数多次编辑:
ifconfig eth0 | sed -e '2s/^.*inet//g' -ne '2s/net.*$//gp'
# 做法是:用括号()扩展正则,将匹配到的看作整体,在替换的字符后面用\n引用,最后只展示引用过的
# 删除文件每行的第一个字符。
sed -n 's/^.//gp' /etc/passwd
sed -nr 's/(.)(.*)/\2/p' /etc/passwd
# 删除文件每行的第二个字符。
sed -nr 's/(.)(.)(.*)/\1\3/p' /etc/passwd
# 删除文件每行的最后一个字符。
sed -nr 's/.$//p' /etc/passwd
sed -nr 's/(.*)(.)/\1/p' /etc/passwd
# 删除文件每行的倒数第二个字符。
sed -nr 's/(.*)(.)(.)/\1\3/p' /etc/passwd
# 为文件前三行开头添加@符号
sed -r '1,3s/(^.)/@\1/' a.txt
# 为文件前三行空格开头添加@符号
sed -r '1,3s/(^[[:space:]])/@\1/g' e.txt
# 调换/etc/passwd第1列和最后一列内容
sed -nr 's/(.*):x(.*):(.*)/\3:x\2:\1/gp' passwd.txt
2.4、sed 命令新增
# 在文件每一行下面添加分隔符,全局匹配
sed 'a --------------' a.txt
# 匹配zkc开头的行,在该行的下一行新增内容
sed '/^zkc/a hello' a.txt
# 在文件第二行下一行新增内容
sed '2a ###2a###' a.txt
# 在文件第二行上一行添加内容
sed '2i ####2i###' a.txt
# 在文件第二行上一行添加多行内容(多行内容中间用\n换行符)
sed '2i ####第一行###\n###第二行####' a.txt
# 将文件第二行替换成aaaaa
sed '2c aaaaa' a.txt
# 这种特殊一点,先将2、3、4行删除,再新增一行helloworld
sed '2,4c helloworld' a.txt
# 字符转换,大写转小写。注意是字符是一一对应的,跟顺序没关系
sed 'y/abcdef/ABCDEF/' a.txt # a-A b-B c-C
sed 'y/abcdef/BFEDCA/' a.txt # a-B b-F c-E
2.5、sed 命令从文件中读取内容
# 将文件2中的内容读入1中,会在1中的每一行后都读入2的内容
sed 'r 2.txt' 1.txt
# 将文件2的内容在1的第3行之后插入(可用于向文件中插入内容)
sed '3r 2.txt' 1.txt
# 将文件2的内容在匹配到的245的行之后插入,如果1中有多行匹配245则在每一行之后都会插入
sed '/245/r 2.txt' 1.txt
# 将将文件2的内容在1的最后一行之后插入
sed '$r 2.txt' 1.txt
2.6、sed命令向文件中写入内容
# 将文件1.txt的内容写入2文件,如果2文件不存在则创建,如果2存在则覆盖之前的内容
sed -n 'w 2.txt' 1.txt
# 将文件1.txt中的第2行内容写入到文件2.txt
sed -n '2w 2.txt' 1.txt
# 将1.txt的第1行和最后一行内容写入2.txt
sed -n -e '1w 2.txt' -e '$w 2.txt' 1.txt
# 将1.txt的第1行和最后一行分别写入2.txt和3.txt
sed -n -e '1w 2.txt' -e '$w 3.txt' 1.txt
# 将1.txt中匹配abc或123的行的内容,写入到2.txt中
sed -n '/abc\|123/w 2.txt' 1.txt
# 将1.txt中从匹配666的行到最后一行的内容,写入到2.txt中
sed -n '/666/,$w 2.txt' 1.txt
# 将1.txt中从匹配xyz的行及其后2行的内容,写入到2.txt中
sed -n '/xyz/,+2w 2.txt' 1.txt
二、 awk 管道命令
awk 是一种用于文本处理和分析的工具。它可以从文件或标准输入中读取数据,并使用预定义的模式和操作对其进行处理和分析
1、awk 基础用法
1.1、awk 语法
awk [选项] 'pattern{action}' 文件名...
1.2、常用选项
* -F :指定以fs作为输入行的分隔符,awk命令默认分隔符为空格或者制表符
* -f file:从脚本文件中读取awk脚本指令,以取代直接在命令行中输入指令
* -v var=value:执行处理过程之前,设置一个变量var,初始值为val
awk的强大在于脚本命令,有两部分组成,分别是匹配规则和执行命令
# 格式:'匹配规则{执行命令}'
* 匹配规则用来指定脚本命令可以作用到文本内容中的具体行,可以使用字符串或者正则表达式指定。
* 整个脚本命令是用单引号括起来,而其中的执行命令部分需要用大括号括起来。
* awk 外层使用单引号,内层必须使用双引号
* 匹配规则是正则表达式时,写法:/正则表达式/
1.3、主要特性
就是处理文本文件中数据的能力,它会自动给一行中的每个数据元素分配一个变量。
默认情况下,awk会将如下变量分配给它在文本行中发现的数据字段。
* $0代表整个文本的行
* $1代表文本行中的第一个数据字段
* $2代表文本行中的第二个数据字段
* $n代表文本行中的第n个数据字段
*
1.4、awk 内置变量
* NR表示行号,NR==5表示行号是5的那一行(一个=是修改变量值,两个==是关系运算符等于)
* FNR代表多个文件分别显示行号,不用FNR的话多个文件会看作一个整体统计行号
* NF表示文本总字段数
* FS代表输入分隔符
* OFS代表输出分隔符,awk默认输出时是空格分隔符,而且必须加逗号操能显示。可以通过 -v OFS='分隔符' 来指定
* RS代表输入记录行与行之间分隔符(输入换行符),默认是每行结束的标记回车符
* ORS代表输出记录行与行之间分隔符(输出换行符),默认是每行结束的标记回车符
# 输出一列
awk '{print $1}' a.txt
# 一次性输出多列
awk '{print $1,$2,$5}' a.txt
# 自定义输出格式
awk '{print "第一列:"$1,"第二列:$2,"第三列:"$5}' a.txt
awk '{print "第一行内容是:"$0}' a.txt
# 找出所有普通用户的用户名和home路径
awk -F ':' '$3>1000{print $1,$(NF-1)}'
# 显示文件第五行
awk 'NR==5' a.txt
awk 'NR>5{print $0}' a.txt # 显示大于5行的 6,7,8,9,10..行
awk 'NR>=5{print $0}' a.txt # 显示大于等于5行的 5,6,7,8..行
awk 'NR<5{print $0}' a.txt # 显示小于5行的 1,2,3,4
awk 'NR<=5{print $0}' a.txt # 显示小于等于5行的 1,2,3,4,5
awk 'NR!=5{print $0}' a.txt # 除过第5行,其他都显示
# 显示文件第 5-10 行
awk 'NR==5,NR==10' a.txt
# 显示文件第 5-10 行,并打印出来每行第一列
awk -F ',' 'NR==5,NR==10{print $1}' a.txt
# 给每一行的内容添加行号,等同于cat -n
awk '{print NR,$0}' a.txt
# 显示3-5行且输出行号,等同于cat -n
awk 'NR==3,NR==5{print NR,$0}' a.txt
# 多个文件分别显示行号
# 两个文件看作一个整体来统计行号
awk -F ':' '{print NR,$1,$(NF-1),$(NF)}' pwd.txt a.txt
# 两个文件分别来统计行号
awk -F ':' -v OFS='\t' '{print FNR,$NF,$(NF-1)}' pwd.txt a.txt
# 打印最后一行
awk 'END{print $0}' a.txt
# 显示文件的第一列、倒数第二列和最后一列
awk -F ':' '{print $1}' a.txt # 第一列
awk -F ':' '{print $NF}' a.txt # 最后一列 写成 $(NF)也可以
awk -F ':' '{print $(NF-1)}' a.txt # 倒数第二列
# 冒号为分隔符。打印出第一和最后一列,输出分隔符为制表符\t
awk -F ':' -v OFS="\t" '{print $1,$(NF)}' a.txt
awk -v FS=':' -v OFS="\t" '{print $1,$(NF)}' a.txt
awk 'BEGIN{FS=" ";OFS="@@@@"}NR==3{print $0}' a.txt
# 更改每行的输入换行符
# 更改源文件每行的换行符,默认是回车符,改成每行到@就算一行结束,后面的算第二行,以此类推
awk -F ':' -v RS='@' '{print $0}' a.txt
# 更改显示的每行的输出换行符
# 更改输出记录的每一行的换行符,默认是回车符,改成每行结尾是@@@@,没有使用默认的换行
awk -v RS=' ' -v ORS="@@@@" '{print $0}' a.txt
awk 'BEGIN{RS=" ";ORS="@@@@"}{print $0}'
# 寻找ip地址
ifconfig etho | awk 'NR==2{print $2}'
# 统计nginx访客数
awk '{print $1}' | sort -n | uniq | wc -l
# 找出访问最频繁的10个ip
awk '{print $1}' | sort -n | uniq -c | sort -nr | head -10
# 查看Nginx 1点到5点半的日志
awk -F"[: /]" '$7":"$8 >= "01:00" && $7":"$8 <="05:30"' /var/log/nginx/access.log
# 匹配规则是正则表达式时,写法:/正则表达式/
# 在文件中空白行输出blankline
awk '/^$/{print "Blank line"}' test.txt
# 找出以/sbin/nologin结尾的行
awk '/\/sbin\/nologin/{print NR,$0}' pwd.txt
# 找出以root开头,到ntp开头的行,多个正则表达式
awk '/^root/,/^ntp/{print NR,$0}' pwd.txt
# 当指定多个分隔符时,用[分隔符1 分隔符2]
# 以空格和冒号为分隔符,打印出不含空行的列
awk -F "[ :]" '!/^$/{print $4}' a.txt
2、awk 高级用法
这里 BEGIN 是模式动作,表示在执行后面操作前,先执行BEGIN模式指定的动作
这里 END 是模式动作,表示在执行前面操作后,再执行END模式指定的动作
# bengin不需要数据源,可以单独执行
awk 'BEGIN{print "hello world"}'
# 这里 BEGIN 是模式动作,表示在执行后面操作前,先执行BEGIN模式指定的动作
awk 'BEGIN{print "我要开始输出了"} {print $0}' a.txt
# 这里 END 是模式动作,表示在执行前面操作后,再执行END模式指定的动作
awk '{print $0}END{print "我已经输出了"}' a.txt
# 自定义变量
awk -v myname="zkc" 'BEGIN{print "我的名字是:",myname} {pring $0}' a.txt
# 把整个文档的第四段相加,求和
awk -F ':' -v sum=0 '{sum=sum+$4};END{print sum}' passwd.txt
awk -F ':' '{sum+=$4};END{print sum}' passwd.txt
awk -F ':' '{sum=sum+$4};END{print sum/NR}' passwd.txt
2.1、awk 定义变量
# 计算内存使用率
head -2 /proc/meminfo | awk 'NR==1{t=$2}NR==2{f=$2;print (t-f)*100/t "%"}'
2.2、awk 定义数组
数组定义方式:数组名[索引]=值
# 定义数组array,有两个元素分别时100,200。打印数组元素
awk 'BEGIN{array[0]=100;array[1]=200;print array[0],array[1]}'
2.3、awk 运算
1、赋值运算 =
主要对变量或者数组赋值
awk -v name='zkc' 'BEGIN{print name}'
awk 'BEGIN{name="school";print name}'
awk 'BEGIN{array[0]=10;array[1]=20;print array[0],array[1]}'
2、比较运算 > >= < <= == !=
若比较的时字符串,则安装ascii码顺序表比较,结果返回值用1表示,返回假用0表示
awk 'BEGIN{print "a" >= "b"}' # 返回0
awk 'BEGIN{print 100 >= 1}' # 返回0
# 筛选第一列大于4的内容
awk '$1>4{print $0}' a.txt
3、数学运算 + - * / % ** ++ –
awk 'BEGIN{print 100+3}'
awk 'BEGIN{print 100-3}'
awk 'BEGIN{print 100*3}'
awk 'BEGIN{print 100/3}'
awk 'BEGIN{print 100**3}'
awk -v "count=0" 'BEGIN{count++;print count}'
awk -v "count=0" 'BEGIN{count--;print count}'
4、逻辑运算 && ||
awk 'BEGIN{print 100>=2 && 100<=4}'
awk 'BEGIN{print 100>=2 || 100<=4}'
5、匹配运输 ~ !~
# 精确匹配
awk -F ":" '$1=="root"{print $0}'passwd.txt
# 模糊匹配
awk -F ":" '$1 ~ "^ro"{print $0}' passwd.txt
awk -F ":" '$1 !~ "^ro"{print $0}' passwd.txt
2.4、awk 流程控制
1、if 判断语句
seq 1 10 >num
awk '{if($1>5)print $0}' num
awk '{if($1<5)print $1*2;else print $1/2}' num
2、for 循环语句
# 把整个文档的第四列相加,求和
awk -F ':' -v sum=0 '{sum=sum+$4};END{print sum}' passwd.txt
awk -F ':' '{sum+=$4};END{print sum}' passwd.txt
awk -F ':' '{sum=sum+$4};END{print sum/NR}' passwd.txt
# 对每一行进行求和
echo 60 50 100 > num2
echo 150 30 10 >> num2
echo 60 110 40 >> num2
awk '{sum=0;for (i=1;i<4;i++){sum+=$i}print sum}' num2
[root@foundylee zkc1]# awk '{
sum=0;
for(i=1;i<4;i++)
sum=sum+$i
print sum}' num2
210
190
210
3、while 循环语句
# 当每行的和大于150就打印
awk '{sum=0;i=1;while(sum<150){sum=sum+$i;i++};print sum}' num2
awk '{sum=0;i=1;do{sum+=$i;i++} while(sum<150);print sum}' num2
# 对每一行进行求和两种写法
awk '{sum=0;i=1;while(i<4){sum=sum+$i;i++}print sum}' num2
[root@foundylee zkc1]# awk '{
> sum=0
> i=1
> while(i<4)
> {
> sum+=$i
> i++
> }
> print sum
> }' num2
210
190
210
4、循环控制语句
# 当每行数的和大于150就停止累加
awk '{sum=0;i=1;while(i<4){sum+=$i;if(sum>150){break}i++}print sum}' num2
[root@foundylee zkc1]# awk '{
> sum=0
> i=1
> while(i<4)
> {
> sum+=$i
> if(sum>150)
> {
> break
> }
> i++
> }
> print sum
> }' num2
210
180
170