SHELL—文本处理(三) : sed与awk

一.sed命令

  • sed(stream editor)处理机制:

        可以指定处理某些行

        sed一次处理一行内容,处理时,把当前处理的行存储在临时缓冲区中,称之为“模式空间“

        处理完成后将缓冲区的内容送至屏幕,然后接着处理下一行内容

             

  • 常用参数:

sed [参数] '命令' file
	p	##显示,将指定的需求行打印显示
        d	##删除,不会影响原文件
	a	##添加,在a的后面接字符串,可以实现在当前指定行的下以行出现该字符串
	c	##替换,c的后面接字符串,可以将指定行内容更改为该字符串
	i	##插入,i的后面接字符串,可以在指定行的上一行插入该字符串
-i         ##更改原文件内容
  • p    ##显示
[root@localhost mnt]# 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@localhost mnt]# sed -n '/\:/p' /etc/fstab      ##显示存在符号:的行
# Created by anaconda on Wed May  7 01:22:57 2014
[root@localhost mnt]# 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@localhost mnt]# sed -n '/^#/!p' /etc/fstab    ##显示不以#开头的行

UUID=9bf6b9f7-92ad-441b-848e-0257cbb883d1 /                       xfs     defaults        1 1
[root@localhost mnt]# 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@localhost mnt]# 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     ##删除
sed '/^UUID/d' /etc/fstab     ##删除以UUID为开头的行
sed '/^#/d' /etc/fstab        ##删除以#开头的行
sed '/^$/d' /etc/fstab        ##删除空行
sed '1,4d' /etc/fstab         ##删除第一行到第四行
  • a   ##添加
[root@localhost mnt]# vim westos
[root@localhost mnt]# cat westos 
hello
[root@localhost mnt]# sed '/hello/aworld' westos    ##在hello下一行添加字符串world
hello
world
[root@localhost mnt]# sed 's/hello/hello world/g' westos    ##在全文的hello后添加world
hello world
[root@localhost mnt]# sed 's/hello/hello\nworld/g' westos    ##在全文的hello后添加换行和字符串world
hello
world
  • c  ##替换
[root@localhost mnt]# sed '/hello/chello world' westos   ##将hello替换为字符串hello world
hello world
  • i   ##插入
[root@server mnt]# sed '/hello/iworld\nwestos' westos  ##在hello的上一行插入world和换行westos
world
westos
hello
  • -i     ##改变原文件内容

练习:

将httpd服务的端口改为8080

[root@localhost mnt]# vim http.sh
[root@localhost mnt]# cat http.sh 
#!/bin/bash
yum install httpd -y &> /dev/null
sed -i "/^Listen/cListen $1" /etc/httpd/conf/httpd.conf && echo -e "Port changed $1 success"
systemctl restart httpd
[root@localhost mnt]# sh http.sh 8080
Port changed 8080 success
[root@localhost mnt]# vim http.sh
[root@localhost mnt]# sh http.sh 80
Port changed 80 success

二.awk命令

1.awk处理机制:

  • awk是被设计用于文本处理,并通常被用作数据提取和报告工具的解释性程序设计语言
  • 根据模式一次从文件中抽取一行文本,对这行文本进行切片(默认使用空白字符作为分隔符)

[root@localhost mnt]# cat test
this     | is   | a  | file
 $1     $2  $3    $4

[root@localhost mnt]# vim test
[root@localhost mnt]# cat test
this is a file
[root@localhost mnt]# awk '{print $0}' test
this is a file
[root@localhost mnt]# awk '{print $1}' test
this
[root@localhost mnt]# awk '{print $2}' test
is
[root@localhost mnt]# awk '{print $3}' test
a
[root@localhost mnt]# awk '{print $4}' test
file
  • -F    ##该参数表示以什么为分隔符
[root@localhost mnt]# awk -F ":" '{print $1,$3}' /etc/passwd   ##以:为分隔符,打印第1列与第三列内容
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7

2.awk常用变量

  • 打印文件名与行号
[root@localhost mnt]# awk '{print FILENAME,NR}' /etc/passwd   ##打印文件名与行号
/etc/passwd 1
/etc/passwd 2
/etc/passwd 3
/etc/passwd 4
/etc/passwd 5
/etc/passwd 6
/etc/passwd 7
/etc/passwd 8
/etc/passwd 9
/etc/passwd 10
/etc/passwd 11
/etc/passwd 12
/etc/passwd 13
  • 打印行号和字段数量
[root@localhost mnt]# awk -F: '{print NR,NF}' /etc/passwd  ##以:为分隔符,打印行号和字段数量
1 7
2 7
3 7
4 7
5 7
6 7
7 7
8 7
9 7
10 7
11 7
12 7
  • 打印以/bash为结尾的行
[root@localhost mnt]# awk -F: '/bash$/{print}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
student:x:1000:1000:Student User:/home/student:/bin/bash
  • 打印第三行
[root@localhost mnt]# awk -F: 'NR==3 {print}' /etc/passwd
daemon:x:2:2:daemon:/sbin:/sbin/nologin
  • 打印偶数行
[root@localhost mnt]# awk -F: 'NR % 2 ==0 {print}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
halt:x:7:0:halt:/sbin:/sbin/halt
operator:x:11:0:operator:/root:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/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
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
  • 打印第三行至第五行
[root@localhost mnt]# awk -F: 'NR >=3 && NR<=5 {print}' /etc/passwd
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
  • 打印uid小与等于2的用户名和uid
[root@localhost mnt]# awk -F: '$3 >=0 && $3 <=2 {print $1,$3}' /etc/passwd
root 0
bin 1
daemon 2

3.awk的BEGIN与END用法

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

练习:

  • 在打印文件前在开头与结尾添加指定字符
[root@localhost mnt]# awk -F: 'BEGIN{print "REDHAT"} {print NR;print } END {print "WESTOS"}' passwd    ##文件开头加REDHAT,末尾加WESTOS,打印行号和内容
REDHAT
1
root:x:0:0:root:/root:/bin/bash
2
bin:x:1:1:bin:/bin:/sbin/nologin
...
39
tcpdump:x:72:72::/:/sbin/nologin
40
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
WESTOS
[root@localhost mnt]# 
  • 统计文本总字段数量
[root@localhost mnt]# cat linux.txt 
123
123 12

12
12 12 123
[root@localhost mnt]# awk 'BEGIN{i=0}{i+=NF}END{print i}' linux.txt   ##统计字段数里
7
[root@localhost mnt]# 

4.awk的高级应用(if,for,while)

1)if单分支语句

扫描二维码关注公众号,回复: 4977427 查看本文章
[root@localhost mnt]# awk -F: 'BEGIN{i=0}{if($7~/bash$/){i++}}END{print i}' /etc/passwd  ##统计登录shell为bash的用户
2

2)if双分支语句

[root@localhost 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

3)for循环

[root@localhost mnt]# awk 'BEGIN{for(i=1;i<=5;i++){print i}}'   ##打印1至5
1
2
3
4
5

4)while循环

[root@localhost mnt]# awk 'i=1 {} BEGIN {while (i<3) {i++;print i}}' test.sh   ##打印1至3的序列,生成该文件
1
2
3
[root@localhost mnt]# 
[root@localhost mnt]# awk 'BEGIN {do {++i;print i} while (i<3)}' test.sh
1
2
3

练习:

  • 嵌套循环
[root@localhost mnt]# cat qiantao.sh 
#!/bin/bash

for((a=1;a<=3;a++))
do
    echo "Starting outside loop: $a"
    for((b=1;b<=3;b++))
    do
        echo "Inside loop: $b"
    done
done
[root@localhost mnt]# sh qiantao.sh 
Starting outside loop: 1
Inside loop: 1
Inside loop: 2
Inside loop: 3
Starting outside loop: 2
Inside loop: 1
Inside loop: 2
Inside loop: 3
Starting outside loop: 3
Inside loop: 1
Inside loop: 2
Inside loop: 3
  • 生成9*9乘法表
[root@localhost mnt]# vim 99.sh
[root@localhost mnt]# cat 99.sh 
#!/bin/bash

##打印9*9乘法表
#1*1=1
#2*1=2 2*2=4
#3*1=3 3*2=6 3*3=9

for i in $(seq 9)
do
    for j in $(seq $i)
        do
            echo -ne "$i*$j=$(($i*$j))\t"
        done
    echo -e "\n"
done
[root@localhost mnt]# sh 99.sh 
1*1=1	

2*1=2	2*2=4	

3*1=3	3*2=6	3*3=9	

4*1=4	4*2=8	4*3=12	4*4=16	

5*1=5	5*2=10	5*3=15	5*4=20	5*5=25	

6*1=6	6*2=12	6*3=18	6*4=24	6*5=30	6*6=36	

7*1=7	7*2=14	7*3=21	7*4=28	7*5=35	7*6=42	7*7=49	

8*1=8	8*2=16	8*3=24	8*4=32	8*5=40	8*6=48	8*7=56	8*8=64	

9*1=9	9*2=18	9*3=27	9*4=36	9*5=45	9*6=54	9*7=63	9*8=72	9*9=81	

[root@localhost mnt]# 

猜你喜欢

转载自blog.csdn.net/daizheng12345/article/details/85341499