shell 之 sed和awk

sed

  1. sed基础知识
    sed(stream editor):
    一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,处理完成之后把缓冲区的内容送往屏幕,接着处理下一行,这样不断重复,直到文件末尾。(不改变文件内容,只是显示出所做的改变)
  2. Sed 对字符的处理
sed     [参数]  ‘命令’     file
		p	##显示
		d	##删除
		a	##添加
		c	##替换
		i	##插入
        s   ##替换
        w   ##整合

  • p  显示,将某个选择的数据打印显示。通常 p 会与参数 sed -n 一起执行

    [root@fuwu test]# cat -n /etc/fstab 
           1	
           2	#
           3	# /etc/fstab
           4	# Created by anaconda on Wed May  7 01:22:57 2014
           5	#
           6	# Accessible filesystems, by reference, are maintained under '/dev/disk'
           7	# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
           8	#
           9	UUID=9bf6b9f7-92ad-441b-848e-0257cbb883d1 /                       xfs     defaults        1 1
      [root@fuwu test]# sed -n '/\:/p' /etc/fstab   ##显示含有:的行(:需要转译)
      # Created by anaconda on Wed May  7 01:22:57 2014
      [root@fuwu test]# sed -n '/^#/p' /etc/fstab    ##显示以#开头的行
      #
      # /etc/fstab
      # Created by anaconda on Wed May  7 01:22:57 2014
      #
      # Accessible filesystems, by reference, are maintained under '/dev/disk'
      # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
      #
      [root@fuwu test]# sed -n '/^#/!p' /etc/fstab        ##显示不以#开头的行
        
      UUID=9bf6b9f7-92ad-441b-848e-0257cbb883d1 /                       xfs     defaults        1 1
      [root@fuwu test]# sed -n '2,6p' /etc/fstab       ##显示2-6行
      #
      # /etc/fstab
      # Created by anaconda on Wed May  7 01:22:57 2014
      #
      # Accessible filesystems, by reference, are maintained under '/dev/disk'
      [root@fuwu test]# sed -n '2,6!p' /etc/fstab   ##显示除了第2行和第6行的行
      # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
      #
      UUID=9bf6b9f7-92ad-441b-848e-0257cbb883d1 /                       xfs     defaults        1 1     
    
  • d  删除,显示模式空间删除指定行后的内容,不会对原文件数据删除

[root@fuwu test]# sed '/^UUID/d' /etc/fstab     ##删除以UUID开头的行

#
# /etc/fstab
# Created by anaconda on Wed May  7 01:22:57 2014
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
[root@fuwu test]# sed '/^$/d' /etc/fstab       ##删除空行
#
# /etc/fstab
# Created by anaconda on Wed May  7 01:22:57 2014
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
UUID=9bf6b9f7-92ad-441b-848e-0257cbb883d1 /                       xfs     defaults        1 1
[root@fuwu test]# sed '1,4d' /etc/fstab        ##删除1-4行
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
UUID=9bf6b9f7-92ad-441b-848e-0257cbb883d1 /                       xfs     defaults        1 1
  • a  添加,a 的后面可以接字符串,该字符串会在当前指定行的下一行出现
[root@fuwu test]# cat hello.sh 
hello
[root@fuwu test]# sed '/hello/aworld' hello.sh
hello
world
[root@fuwu test]# sed 's/hello/hello world/g' hello.sh 
hello world
[root@fuwu test]# sed 's/hello/hello\nworld/g' hello.sh 
hello
world

  • c  更改, c 的后面可以接字符串,该字符串可以取代 n1,n2 之间的行
[root@fuwu test]# sed '/hello/chello world' hello.sh 
hello world
  • i    插入, i 的后面可以接字符串,该字符串会在当前指定行的上一行出现
[root@fuwu test]# sed '/hello/iworld\nwestos' hello.sh 
world
westos
hello
  • s:替换,格式sed ‘s/A/B/g’ passwd ##将passwd文件中的所有的A替换成B
[root@squid mnt]# cat passwd
	root:x:0:0:root:/root:/bin/bash
	bin:x:1:1:bin:/bin:/sbin/nologin
	daemon:x:2:2:daemon:/sbin:/sbin/nologin
	adm:x:3:4:adm:/var/adm:/sbin/nologin
	lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
	sync:x:5:0:sync:/sbin:/bin/sync
	shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
	halt:x:7:0:halt:/sbin:/sbin/halt
	mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
	operator:x:11:0:operator:/root:/sbin/nologin
[root@squid mnt]# sed 's/nologin/bash/g' passwd
	root:x:0:0:root:/root:/bin/bash
	bin:x:1:1:bin:/bin:/sbin/bash
	daemon:x:2:2:daemon:/sbin:/sbin/bash
	adm:x:3:4:adm:/var/adm:/sbin/bash
	lp:x:4:7:lp:/var/spool/lpd:/sbin/bash
	sync:x:5:0:sync:/sbin:/bin/sync
	shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
	halt:x:7:0:halt:/sbin:/sbin/halt
	mail:x:8:12:mail:/var/spool/mail:/sbin/bash
	operator:x:11:0:operator:/root:/sbin/bash

1. sed 's/nologin/bash/g' passwd  ##将passwd文件中的所有的nologin替换成bash
2. sed '1,5s/nologin/bash/g' passwd  ##将passwd文件中1到5行的nologin替换成bash
3. sed -e '2s/nologin/bash/g;4s/nologin/bash/g' passwd  ##将passwd文件中2和4行的nologin替换成bash

在sed替换中@相当于/  
1. sed ‘s@\/@ @g’ passwd  ##将passwd中的/替换成空格
2. sed ‘G’ passwd  ## 将passwd文件每一行后加入一个空行
3. sed ‘$!G’ passwd  ## 将passwd文件每一行后加入一个空行,除了最后一行
  • w 整合,
[root@squid mnt]# cat fstab 
	
	#
	# /etc/fstab
	# Created by anaconda on Wed May  7 01:22:57 2014
	#
	# Accessible filesystems, by reference, are maintained under '/dev/disk'
	# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
	#
	UUID=9bf6b9f7-92ad-441b-848e-0257cbb883d1 /                       xfs     defaults        1 1
[root@squid mnt]# touch testfile
[root@squid mnt]# sed '/^#/w /mnt/testfile' fstab
[root@squid mnt]# cat testfile 
	#
	# /etc/fstab
	# Created by anaconda on Wed May  7 01:22:57 2014
	#
	# Accessible filesystems, by reference, are maintained under '/dev/disk'
	# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
	#

例:

1. sed '/^#/w /etc/testfile' fstab   ###将fstab中的以#开头的行整合到/etc/testfile中
2. sed '5r /etc/hello' /mnt/fstab   ###将/etc/hello文件内容整合到/mnt/fstab的第五行
3. sed 'r /etc/hello' /mnt/fstab    ##将/etc/hello文件内容整合到/mnt/fstab的每一行

注意:添加或者整合到文件的最后一行时用追加的形式:echo ‘’
      添加或者整合时添加多行要用 \n来换行
  • 练习:更改httpd服务的端口

    [root@fuwu test]# cat dk.sh 
    #!/bin/bash
    
    yum install -y httpd &> /dev/null
    sed -i "/^Listen/cListen $1" /etc/httpd/conf/httpd.conf
    echo -e "Port has changed!"
    echo "Now ,Port is $1!"
    systemctl restart httpd
    [root@fuwu test]# sh dk.sh 8080
    Port has changed!
    Now ,Port is 8080!
    

awk:报告生成器

  1. awk处理机制:awk 会逐行处理文本,支持在处理第一行之前做一些准备工作,以及在处理完最后一行做一些总结性质的工作, 根据模式一次从文件中抽取一行文本,对这行文本进行切片(默认使用空白字符作为分隔符)。在命令格式上分别体现如下:
  • BEGIN{}:读入第一行文本之前执行,一般用来初始化操作。
  • {}:逐行处理,逐行读入文本执行相应的处理,是最常见的编辑指令块。
  • END{}:处理完最后一行文本之后执行,一般用来输出处理结果。
[root@fuwu test]# cat ll.sh 
this   is   a   apple
$1   $2  $3    $4
[root@fuwu test]# awk '{print $0}' ll.sh    ##$0表示输出一整行
this  is  a  apple
[root@fuwu test]# awk '{print $1}' ll.sh     
this
[root@fuwu test]# awk '{print $1,$2}' ll.sh    ##显示两个字段
this is

  1. 指定分隔符
[root@fuwu test]# awk -F ":" '{print $1,$3}' /etc/passwd     ###以:为分隔符,打印文件/etc/passwd的第一列和第三列
root 0  
bin 1
daemon 2
adm 3
lp 4
sync 5
....
[root@fuwu test]# awk '{print FILENAME,NR}' /etc/passwd
/etc/passwd 1
/etc/passwd 2
/etc/passwd 3
/etc/passwd 4
/etc/passwd 5
...
  1. awk的常用变量
[root@fuwu test]# awk '{print FILENAME,NR}' /etc/passwd      ####打印文件/etc/passwd的文件命令和行号
/etc/passwd 1
/etc/passwd 2
/etc/passwd 3
/etc/passwd 4
/etc/passwd 5
...
[root@fuwu test]# awk -F: '{print NR,NF}' /etc/passwd   ###打印文件/etc/passwd的行号和以":"为分隔符的字段个数
1 7
2 7
3 7
...
[root@fuwu test]# awk -F: '$3 >= 0 && $3 < 2 {print $1,$3}' /etc/passwd   ###输出/etc/passwd下uid小于等于2的用户名和uid
root 0
bin 1

awk两个特殊模式(BEGIN 和 END)

BEGIN{}: 读入第一行文本之前执行的语句,一般用来初始化操作
{}: 逐行处理
END{}: 处理完最后以行文本后执行,一般用来处理输出结果

[root@fuwu test]# awk 'BEGIN { a=14;print a+134 }'
148


[root@fuwu test]# awk -F: 'BEGIN{print "REDHAT"} {print NR;print } END {print "WESTOS"}' /etc/passwd   ####文件开头加REDHAT,末尾加WESTOS,打印行号和内容
REDHAT
1
root:x:0:0:root:/root:/bin/bash
2
bin:x:1:1:bin:/bin:/sbin/nologin
3
daemon:x:2:2:daemon:/sbin:/sbin/nologin
4
adm:x:3:4:adm:/var/adm:/sbin/nologin
5
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
....

统计文本总字段个数

[root@fuwu test]# cat ll.sh
this  is  a  apple
fsg hh
fds  
dfgg
[root@fuwu test]# awk 'BEGIN{i=0}{i+=NF}END{print i}' ll.sh 
8

awk示例:

1. 能登陆到系统的用户名称
	[root@squid mnt]# awk -F : '/bash$/{print $1}' passwd 
		root
		student
2. 能登陆到系统的用户个数
	[root@squid mnt]# awk -F : BEGIN{i=0}'/bash$/{i++}END{print i}' passwd
		2
3. 能登陆到系统但是家目录不在home下的系统用户名称
	[root@squid mnt]# awk -F : '$6!~/\<home$/&&/bash$/{print $1}' passwd 
		root
		student
		注意:“\<  此符号为不要有扩展的意思”
4. 能登陆到系统但是家目录不在home下的系统用户个数
	[root@squid mnt]# awk -F : BEGIN{i=0}'$6!~/\<home$/&&/bash$/{i++}END{print i}' passwd 
		2
5. 打印passwd文件中以a或b或c或d开头的行
	[root@squid mnt]# awk '/^[a-d]/{print}' passwd
		bin:x:1:1:bin:/bin:/sbin/nologin
		daemon:x:2:2:daemon:/sbin:/sbin/nologin
		adm:x:3:4:adm:/var/adm:/sbin/nologin
		dbus:x:81:81:System message bus:/:/sbin/nologin
		avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
		avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin
		chrony:x:998:996::/var/lib/chrony:/sbin/nologin
		colord:x:997:995:User for colord:/var/lib/colord:/sbin/nologin
		abrt:x:173:173::/etc/abrt:/sbin/nologin
		apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
6. 打印除了以a-k开头的行
	[root@squid mnt]# awk '!/^[a-t]/{print}' passwd
		usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin
		unbound:x:995:993:Unbound DNS resolver:/etc/unbound:/sbin/nologin
或者是 : awk '/^[^a-d]/{print}' passwd 
7. 打印以a开头或者以bash结尾的行
	[root@squid mnt]# awk '/^a|bash$/{print}' passwd
		root:x:0:0:root:/root:/bin/bash
		adm:x:3:4:adm:/var/adm:/sbin/nologin
		avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
		avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin
		student:x:1000:1000:Student User:/home/student:/bin/bash
		abrt:x:173:173::/etc/abrt:/sbin/nologin
		apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
8. 打印不是以a开头但是可以以bash结尾的行
	[root@squid mnt]# awk '/!~^a|bash$/{print}' passwd
		root:x:0:0:root:/root:/bin/bash
		student:x:1000:1000:Student User:/home/student:/bin/bash
9. 打印不以a开头不以bash结尾的行
	  [root@squid mnt]# awk '!/^a|bash$/' passwd
		bin:x:1:1:bin:/bin:/sbin/nologin
		daemon:x:2:2:daemon:/sbin:/sbin/nologin
		lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
		sync:x:5:0:sync:/sbin:/bin/sync
		shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
		halt:x:7:0:halt:/sbin:/sbin/halt
		mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
		operator:x:11:0:operator:/root:/sbin/nologin
		games:x:12:100:games:/usr/games:/sbin/nologin
		ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
		nobody:x:99:99:Nobody:/:/sbin/nologin
		dbus:x:81:81:System message bus:/:/sbin/nologin
10. 打印以:为分隔符的第六列以bin结尾的行
	[root@squid mnt]# awk -F : '$6~/\<bin$/{print}' passwd
		bin:x:1:1:bin:/bin:/sbin/nologin
11. 打印以:为分隔符的第六列不以bin结尾的行
	[root@squid mnt]# awk -F : '$6!~/\<bin$/{print}' passwd
		root:x:0:0:root:/root:/bin/bash
		daemon:x:2:2:daemon:/sbin:/sbin/nologin
		adm:x:3:4:adm:/var/adm:/sbin/nologin
		lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
		sync:x:5:0:sync:/sbin:/bin/sync
		shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
		halt:x:7:0:halt:/sbin:/sbin/halt

awk高级应用(条件判断、循环)

  1. if单分支语句
[root@fuwu test]# awk -F: 'BEGIN{i=0}{if($7~/bash$/){i++}}END{print i}' /etc/passwd    ###统计登录shell为bash的用户
4   

[root@fuwu test]# awk -F: 'BEGIN{i=0}{if($3<500){i++}}END{print i}' /etc/passwd    ###统计/etc/passwd下uid小于500的用户个数
31 




[root@fuwu test]# awk 'BEGIN{do {++i;print i} while (i<3)}'
1
2
3



  1. if双分支
[root@server19 mnt]# awk -F: 'BEGIN{i=0;j=0}{if($3<=500){i++}else{j++}}END{print i,j}' /etc/passwd   ###统计uid小于等于500和大于500的用户个数
31 9 
  1. for循环
[root@fuwu test]# awk 'BEGIN{for(i=1;i<=5;i++){print i}}'   ###生成1-5序列
1
2
3
4
5
  1. while循环
[root@fuwu test]# awk 'i=1 {} BEGIN{while (i<3){i++;print i}}' 
1
2
3
[root@fuwu test]# awk 'BEGIN{do {++i;print i} while (i<3)}'
1
2
3
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值