sed和awk命令详解

本文详细介绍了sed和awk这两个强大的文本处理命令。sed主要用于流式文件编辑,其命令语法包括选项说明、操作行格式和实际使用案例。awk则是一个文本分析工具,它按行处理文本并根据分隔符分割字段,支持print、-f指定脚本、匹配代码块、if语句、条件表达式、逻辑运算符、数值运算、输出分隔符、输出到文件、格式化输出、while语句和数组等特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

sed命令

sed命令是一个流式文件编辑命令,针对输入文件的每一行判断是否符合命令语句如果符合就执行相应的操作

sed 命令语法格式

sed [optional] [‘命令语句’] 输入文件

sed 选项说明
-i 使修改作用于输入文件
-n 只打印匹配命令语句的行
-e 指定命令语句表达式
-f 制定包含命令语句的文件
sed 命令说明
a 追加内容到指定行后
i 插入内容到指定行前
d 删除指定行
c 用新行替换旧行
s 对每行第一次匹配到的内容进行替换,可搭配标志g将一行中所有匹配到的内容进行替换
sed 指定操作行的格式
1   匹配第一行|
1,10 匹配第1到第10行
10,+20 匹配第10行到第30行
10,$ 匹配第10行到最后一行
/oldboy/ 匹配有oldboy的行 双斜线中的内容其实是正则表达式
/oldboy/,/alex/ 匹配有oldboy的行到 有alex的行

sed 特殊操作
\1 :反斜杠接数字是sed配合正则的分组匹配的特殊技巧名为后项引用,sed命令在使用正则匹配时会记住圆括号即分组匹配匹配到的内容,使用反斜杠接数字的方式即可取出对应顺序被sed记住的内容,需要注意的是sed最多只能记住九个分组匹配的内容,也就是说反斜杠后面能接的最大的数字是九。
&:在sed匹配中这个符号表示前面需要被替换掉的内容。
sed 实际使用举例
|sed '1a hello world' test.txt| 在第一行后插入hello world 不会修改原文件|
|sed '1i hello world' test.txt| 在第一行前插入hello world 不会修改原文件|
|sed -i '1c 11 AA' test.txt| 将第一行替换 并使修改作用于原文件|
|sed  -n 's/aa/AA/g' test.txt| 将每一行含有的aa替换成AA|
|sed -i '13i Port 52113\nPermitRootLogin no\nPermitEmptyPasswords no\nUseDNS no\nGSSAPIAuthentication no' /etc/ssh/sshd_config|在ssh配置文件的13行之前插入5行配置,每一行配置用\n分隔|
|sed  -i  '7s/enforcing/disabled/'  /etc/selinux/config|修改selinux的配置文件,将selinux的级别从enforcing改为disabled|
|sed -n '/2019-09-06 09:00:[0-9][0-9]/,/2019-09-06 09:3[0-9]:[0-9][0-9]/p' request.log |截取9点到9点半的日志|

awk命令

awk命令是一个文本分析命令,针对输入文件的每一行 判断是否符合程序语句 如果符合就执行相应的操作,awk将文本分成一行一行的处理,每一行又根据分隔符分成若干个字段,默认分隔符为空格,可使用-F 选项指定 分隔符

awk 命令语法格式

awk -F|-f|-v 'BEGIN{ } / / {comand1;comand2} END{ }' file
-F 定义列分隔符
-f 指定调用脚本
-v 定义变量
' '引用代码块,awk执行语句必须包含在内
BEGIN{ } 初始化代码块,在对每一行进行处理之前,初始化代码,主要是引用全局变量,设置FS分隔符
{ } 命令代码块,包含一条或多条命令
// 用来定义需要匹配的模式(字符串或者正则表达式),对满足匹配模式的行进行上条代码块的操作
END{ }  结尾代码块,在对每一行进行处理之后再执行的代码块,主要是进行最终计算或输出结尾摘要信息
特殊要点说明

$0           表示整个当前行
$1           每行第一个字段
NF          字段数量变量
NR          每行的记录号,多文件记录递增
FNR         与NR类似,不过多文件记录不递增,每个文件都从1开始
\t          制表符
\n          换行符
FS          BEGIN时定义分隔符
RS          输入的记录分隔符, 默认为换行符(即文本是按一行一行输入)
~            匹配,与==相比不是精确比较
!~           不匹配,不精确比较
==           等于,必须全部相等,精确比较
!=           不等于,精确比较
&&          逻辑与
||              逻辑或
+              匹配时表示1个或1个以上
/[0-9][0-9]+/   两个或两个以上数字
/[0-9][0-9]*/    一个或一个以上数字
FILENAME 文件名
OFS      输出字段分隔符, 默认也是空格,可以改为制表符等
ORS        输出的记录分隔符,默认为换行符,即处理结果也是一行一行输出到屏幕
-F'[:#/]'   定义三个分隔符

实际使用举例
print 使用

print 是awk打印指定内容的主要命令
awk '{print}'  /etc/passwd   ==   awk '{print $0}'  /etc/passwd  
awk '{print " "}' /etc/passwd                                           //不输出passwd的内容,而是输出相同个数的空行,进一步解释了awk是一行一行处理文本
awk '{print "a"}'   /etc/passwd                                        //输出相同个数的a行,一行只有一个a字母
awk -F":" '{print $1}'  /etc/passwd 
awk -F: '{print $1; print $2}'   /etc/passwd                   //将每一行的前二个字段,分行输出,进一步理解一行一行处理文本
awk  -F: '{print $1,$3,$6}' OFS="\t" /etc/passwd        //输出字段1,3,6,以制表符作为分隔符

-f指定脚本
awk -f script.awk  file
BEGIN{
FS=":"
}
{print $1}               //效果与awk -F":" '{print $1}'相同,只是分隔符使用FS在代码自身中指定
 
awk 'BEGIN{X=0} /^$/{ X+=1 } END{print "I find",X,"blank lines."}' test 
I find 4 blank lines.
 ls -l|awk 'BEGIN{sum=0} !/^d/{sum+=$5} END{print "total size is",sum}'                    //计算文件大小
total size is 17487

匹配代码块
//纯字符匹配   !//纯字符不匹配   ~//字段值匹配    !~//字段值不匹配   ~/a1|a2/字段值匹配a1或a2   
awk '/mysql/' /etc/passwd
awk '/mysql/{print }' /etc/passwd
awk '/mysql/{print $0}' /etc/passwd                   //三条指令结果一样
awk '!/mysql/{print $0}' /etc/passwd                  //输出不匹配mysql的行
awk '/mysql|mail/{print}' /etc/passwd
awk '!/mysql|mail/{print}' /etc/passwd
awk -F: '/mail/,/mysql/{print}' /etc/passwd         //区间匹配
awk '/[2][7][7]*/{print $0}' /etc/passwd               //匹配包含27为数字开头的行,如27,277,2777...
awk -F: '$1~/mail/{print $1}' /etc/passwd           //$1匹配指定内容才显示
awk -F: '{if($1~/mail/) print $1}' /etc/passwd     //与上面相同
awk -F: '$1!~/mail/{print $1}' /etc/passwd          //不匹配
awk -F: '$1!~/mail|mysql/{print $1}' /etc/passwd 

if语句

必须用在{}中,且比较内容用()扩起来
awk -F: '{if($1~/mail/) print $1}' /etc/passwd                                       //简写
awk -F: '{if($1~/mail/) {print $1}}'  /etc/passwd                                   //全写
awk -F: '{if($1~/mail/) {print $1} else {print $2}}' /etc/passwd            //if...else...

条件表达式
==   !=   >   >=  
awk -F":" '$1=="mysql"{print $3}' /etc/passwd  
awk -F":" '{if($1=="mysql") print $3}' /etc/passwd          //与上面相同 
awk -F":" '$1!="mysql"{print $3}' /etc/passwd                 //不等于
awk -F":" '$3>1000{print $3}' /etc/passwd                      //大于
awk -F":" '$3>=100{print $3}' /etc/passwd                     //大于等于
awk -F":" '$3<1{print $3}' /etc/passwd                            //小于
awk -F":" '$3<=1{print $3}' /etc/passwd       

逻辑运算符
&& || 
awk -F: '$1~/mail/ && $3>8 {print }' /etc/passwd         //逻辑与,$1匹配mail,并且$3>8
awk -F: '{if($1~/mail/ && $3>8) print }' /etc/passwd
awk -F: '$1~/mail/ || $3>1000 {print }' /etc/passwd       //逻辑或
awk -F: '{if($1~/mail/ || $3>1000) print }' /etc/passwd

数值运算
awk -F: '$3 > 100' /etc/passwd    
awk -F: '$3 > 100 || $3 < 5' /etc/passwd  
awk -F: '$3+$4 > 200' /etc/passwd
awk -F: '/mysql|mail/{print $3+10}' /etc/passwd                    //第三个字段加10打印 
awk -F: '/mysql/{print $3-$4}' /etc/passwd                             //减法
awk -F: '/mysql/{print $3*$4}' /etc/passwd                             //求乘积
awk '/MemFree/{print $2/1024}' /proc/meminfo                  //除法
awk '/MemFree/{print int($2/1024)}' /proc/meminfo           //取整

输出分隔符OFS
awk '$6 ~ /FIN/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt
awk '$6 ~ /WAIT/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt        
//输出字段6匹配WAIT的行,其中输出每行行号,字段4,5,6,并使用制表符分割字段

输出处理结果到文件
在命令代码块中直接输出    route -n|awk 'NR!=1{print > "./fs"}'   
使用重定向进行输出           route -n|awk 'NR!=1{print}'  > ./fs
格式化输出
netstat -anp|awk '{printf "%-8s %-8s %-10s\n",$1,$2,$3}' 
printf表示格式输出
%格式化输出分隔符
-8长度为8个字符
s表示字符串类型
打印每行前三个字段,指定第一个字段输出字符串类型(长度为8),第二个字段输出字符串类型(长度为8),
第三个字段输出字符串类型(长度为10)
netstat -anp|awk '$6=="LISTEN" || NR==1 {printf "%-10s %-10s %-10s \n",$1,$2,$3}'
netstat -anp|awk '$6=="LISTEN" || NR==1 {printf "%-3s %-10s %-10s %-10s \n",NR,$1,$2,$3}'
while语句
awk -F: 'BEGIN{i=1} {while(i<NF) print NF,$i,i++}' /etc/passwd 
7 root 1
7 x 2
7 0 3
7 0 4
7 root 5
7 /root 6
数组
netstat -anp|awk 'NR!=1{a[$6]++} END{for (i in a) print i,"\t",a[i]}'
netstat -anp|awk 'NR!=1{a[$6]++} END{for (i in a) printf "%-20s %-10s %-5s \n", i,"\t",a[i]}'
9523                               1     
9929                               1     
LISTEN                            6     
7903                               1     
3038/cupsd                   1     
7913                               1     
10837                             1     
9833                               1     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值