Linux Shell 脚本编程学习之【第4章 sed命令最详细 (第一部分)】

第4章 sed命令和awk编程

  • [1 sed命令基本用法](#1 sed命令基本用法)
    • [1.1 sed命令位置](#1.1 sed命令位置)
    • [1.2 sed适用的三种场合](#1.2 sed适用的三种场合)
    • [1.3 sed三种命令格式](#1.3 sed三种命令格式)
    • [1.4 sed命令选项及其意义](#1.4 sed命令选项及其意义)
    • [1.5 sed 两种方式定位文本方法](#1.5 sed 两种方式定位文本方法)
  • [2 sed编辑命令](#2 sed编辑命令)
  • [3 sed 示例](#3 sed 示例)
    • [3.1 -n参数](#3.1 -n参数)
    • [3.2 多个参数同时执行(-e)](#3.2 多个参数同时执行(-e))
    • [3.3 追加文本(-f)](#3.3 追加文本(-f))
  • [4 sed 文本定位例子](#4 sed 文本定位例子)
    • 4.1匹配元字符
    • [4.2 匹配最后一行](#4.2 匹配最后一行)
    • [4.3 匹配以字符结尾的字符串的行](#4.3 匹配以字符结尾的字符串的行)
    • [4.4 取行区间之外(!)](#4.4 取行区间之外(!))
    • [4.5 取行号到匹配行之间](#4.5 取行号到匹配行之间)
  • [5 sed基本编辑命令举例](#5 sed基本编辑命令举例)
    • [5.1 匹配行前面插入(i\)](#5.1 匹配行前面插入(i\))
    • [5.2 替换匹配行(c\)](#5.2 替换匹配行(c\))
    • [5.3 删除匹配行(d)](#5.3 删除匹配行(d))
    • [5.4 替换文本(/s)](#5.4 替换文本(/s))
    • [5.5 写新文件(/w)](#5.5 写新文件(/w))
    • [5.6 从文件中读取(r)](#5.6 从文件中读取(r))
    • [5.7 匹配到行退出(q)](#5.7 匹配到行退出(q))
    • [5.8 变换命令](#5.8 变换命令)
    • [5.9 显示控制字符](#5.9 显示控制字符)
    • [5.10 在匹配行执行命令组](#5.10 在匹配行执行命令组)
  • [6 sed 高级编辑命令示例](#6 sed 高级编辑命令示例)
    • [6.1 处理匹配行的下一行(n)](#6.1 处理匹配行的下一行(n))
    • [6.2 sed缓冲区处理](#6.2 sed缓冲区处理)
    • [6.3 利用分号分隔多个编辑命令](#6.3 利用分号分隔多个编辑命令)

1 sed命令基本用法

1.1 sed命令位置

java 复制代码
[root@localhost etc]# which sed
/bin/sed
[root@localhost etc]# 

1.2 sed适用的三种场合

● 编辑相对交互式文本编辑器而言太大的文件。

● 编辑命令太复杂,在交互式文本编辑器中难以输入的情况。

● 对文件扫描一遍,但是需要执行多个编辑函数的情况。

1.3 sed三种命令格式

java 复制代码
//1、在 Shell命令行输入命令调用sed, 格式为 :
sed [选项]'sed 命令:输入文件
--注意,需要用单引号将 sed 命令引起来。

//2、将 sed  命令插入脚本文件后,然后通过sed  命令调用它,格式为: 
sed [选项]-f sed脚本文件输入文件

//3、将 sed  命令插入脚本文件后,最常用的方法是设置该脚本文件为可执行,然后直接执行该脚本文件,格式为:
./sed 脚本文件输入文件

1.4 sed命令选项及其意义

选 项 意 义
-n 不打印所有行到标准输出
-e 表示将下一个字符串解析为sed编辑命令,如果只传递一个编辑命令给sed,-e选项可以省略
-f 表示正在调用sed脚本文件

1.5 sed 两种方式定位文本方法

● 使用行号,指定一行,或指定行号范围。

● 使用正则表达式。

选 项 意 义
X x为指定行号
x,y 指定从x到y的行号范围
/patterm/ 查询包含模式的行
/pattern/pattern/ 查询包含两个模式的行
/pattern/,x 从与pattern的匹配行到x号行之间的行
x,/pattern/ 从x号行到与pattern的匹配行之间的行
x,y! 查询不包括x和y行号的行

2 sed编辑命令

选 项 意 义
P 打印匹配行
= 打印文件行号
al 在定位行号之后追加文本信息
il 在定位行号之前插入文本信息
d 删除定位行
cl 用新文本替换定位文本
s 使用替换模式替换相应模式
r 从另一个文件中读文本
w 将文本写入到一个文件
y 变换字符
9 第一个模式匹配完成后退出
1 显示与八进制ASCⅡI码等价的控制字符
0 在定位行执行的命令组
n 读取下一个输入行,用下一个命令处理新的行
h 将模式缓冲区的文本复制到保持缓冲区
H 将模式缓冲区的文本追加到保持缓冲区
x 互换模式缓冲区和保持缓冲区的内容
g 将保持缓冲区的内容复制到模式缓冲区
G 将保持缓冲区的内容追加到模式缓冲区

3 sed 示例

3.1 -n参数

java 复制代码
// -n只打印第一行
[root@localhost etc]# sed -n 1p passwd
root:x:0:0:root:/root:/bin/bash

//不加-n打印全部行
[root@localhost etc]# sed -n 1p passwd | wc -l
1
[root@localhost etc]# sed 1p passwd|wc -l
45
[root@localhost etc]# 

//打印2-5行
[root@localhost etc]# sed -n "2,5p" 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
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

//打印匹配行,匹配adm
[root@localhost etc]# sed -n "/adm/p" passwd
adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@localhost etc]# 

3.2 多个参数同时执行(-e)

java 复制代码
[root@localhost etc]# sed -n "/nobody/=" passwd
13
30
[root@localhost etc]# sed -n -e "/nobody/p" -e "/nobody/=" passwd
nobody:x:99:99:Nobody:/:/sbin/nologin
13
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
30
[root@localhost etc]# 

sed不支持同时带多个命令,如

java 复制代码
[root@localhost etc]# sed -n "/nobody/p=" passwd

3.3 追加文本(-f)

java 复制代码
[root@localhost etc]# sed '/rhel:/a\sed a new line.' /home/xj/test.log 
tcpdump:x:72:72::/:/sbin/nologin
rhel:x:1000:1000:rhel:/home/rhel:/bin/bash
sed a new line.     -- 新加的行
xj:x:808:809::/home/xj1:/bin/bash

//写一个sed追加文本的脚本
[root@localhost xj]# vi append.sed 
#!/bin/sed -f
/rhel:/a\                  #a\表示此处换行添加文本
We are family!.\           #"\"符号表示换行
We add a new line.
[root@localhost xj]# chmod +x append.sed 
[root@localhost xj]# ./append.sed test.log 
tcpdump:x:72:72::/:/sbin/nologin
rhel:x:1000:1000:rhel:/home/rhel:/bin/bash
We are family!.           #新加的行
We add a new line.        #新加的行
xj:x:808:809::/home/xj1:/bin/bash

4 sed 文本定位例子

4.1匹配元字符

java 复制代码
[root@localhost xj]# sed -n '/\./p' test.log 
.sdfaj
[root@localhost xj]# sed -n '/\$/p' test.log 
$9999

4.2 匹配最后一行

java 复制代码
[root@localhost xj]# sed -n '$p' test.log 
last line!
[root@localhost xj]# sed -n '$'p test.log 
last line!

4.3 匹配以字符结尾的字符串的行

匹配fix

java 复制代码
[root@localhost xj]# sed -n '/.*fix/p' test.log 
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
[root@localhost xj]# 

4.4 取行区间之外(!)

java 复制代码
[root@localhost xj]# sed -n '2,10!p' test.log 
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
$9999
.sdfaj
last line!
[root@localhost xj]# 

4.5 取行号到匹配行之间

java 复制代码
[root@localhost xj]# sed -n '2,/ntp/p' test.log 
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
[root@localhost xj]# 

5 sed基本编辑命令举例

5.1 匹配行前面插入(i\)

java 复制代码
[root@localhost xj]# cat append.sed 
#!/bin/sed -f
/rhel:/i\
We are family!.\
We add a new line.
[root@localhost xj]# ./append.sed test.log 
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
We are family!.
We add a new line.
rhel:x:1000:1000:rhel:/home/rhel:/bin/bash
[root@localhost xj]# 

5.2 替换匹配行(c\)

java 复制代码
[root@localhost xj]# cat append.sed 
#!/bin/sed -f
/rhel:/c\
We are family!.\
We add a new line.
[root@localhost xj]# ./append.sed test.log 
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
We are family!.
We add a new line.

5.3 删除匹配行(d)

java 复制代码
[root@localhost xj]# cat test.log 
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-
last line!
[root@localhost xj]# sed '1d' test.log 
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-
last line!
[root@localhost xj]# sed '$d' test.log
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
[root@localhost xj]# sed '2,$d' test.log
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

//脚本(不区分大小写)
[root@localhost xj]# cat test.log 
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-
[root@localhost xj]# cat append.sed 
#!/bin/sed -f
/[Ss][Ss][Hh][Dd]/d\
[root@localhost xj]# ./append.sed test.log 
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-

5.4 替换文本(/s)

java 复制代码
//将sshd替换为SSHD
[root@localhost xj]# sed "s/sshd/SSHD/" test.log 
SSHD:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
// 添加参数/p
[root@localhost xj]# sed -n "s/sshd/SSHD/p" test.log 
SSHD:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
// 添加/g将文本中全部sshd替换为SSHD
[root@localhost xj]# sed "s/sshd/SSHD/g" test.log 
SSHD:x:74:74:Privilege-separated SSH:/var/empty/SSHD:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
// 替换第二次匹配
[root@localhost xj]# sed "s/sshd/SSHD/2p" test.log 
sshd:x:74:74:Privilege-separated SSH:/var/empty/SSHD:/sbin/nologin
//将匹配行重定向
[root@localhost xj]# sed "s/sshd/SSHD/w 1.log" test.log 
SSHD:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
[root@localhost xj]# cat 1.log 
SSHD:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
//&符号
[root@localhost xj]# sed "s/sshd/(SSHD)/w 1.log" test.log 
(SSHD):x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
[root@localhost xj]# sed "s/sshd/(&)/w 1.log" test.log 
(sshd):x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
[root@localhost xj]# 

5.5 写新文件(/w)

java 复制代码
[root@localhost xj]# sed -n '/sshd/w 2.log' test.log 
[root@localhost xj]# cat 2.log
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
[root@localhost xj]# 

5.6 从文件中读取(r)

java 复制代码
[root@localhost xj]# cat 2.log 
add a new line from 2.log!
[root@localhost xj]# sed '/sshd/r 2.log' test.log 
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
add a new line from 2.log!

5.7 匹配到行退出(q)

java 复制代码
// 打印第一行后退出
[root@localhost xj]# sed '1 q' test.log 
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
//匹配带h的行,匹配到第一个后退出
[root@localhost xj]# sed -n '/.h.*/p' test.log 
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
[root@localhost xj]# sed '/.h.*/q' test.log 
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

5.8 变换命令

sed y命令要求被变换的字符序列和变换的字符序列等长,否则 sed y命令将报错。

java 复制代码
[root@localhost xj]# cat > 2.log
123
2356
143
^C
[root@localhost xj]# sed 'y/123/ABC/' 2.log 
ABC
BC56
A4C
[root@localhost xj]# 

5.9 显示控制字符

java 复制代码
//注意$l中l为小写的字母l
[root@localhost xj]# sed -n '1,$l' 2.log 
\033[17~\033[18~ \033[18~$
\033[15~$
\033OS$

5.10 在匹配行执行命令组

java 复制代码
//显示匹配行和行号
[root@localhost xj]# sed -n '/sshd/{p;=}' test.log 
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
1
[root@localhost xj]# 
[root@localhost xj]# sed '/sshd/{s/h/H/;s/ss/88/}' test.log 
88Hd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

6 sed 高级编辑命令示例

6.1 处理匹配行的下一行(n)

java 复制代码
[root@localhost xj]# cat test.log 
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
[root@localhost xj]# sed '/sshd/{n;s/un/88/}' test.log 
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/r88/avahi-daemon:/sbin/nologin

6.2 sed缓冲区处理

sed命令将输入文件复制到缓冲区,对缓冲区中的复制内容处理后,将其写入 输出文件。实际上,sed有两种缓冲区:模式缓冲区(Pattern Buffer)和保持缓冲区(Hold Buffer)。 前面提及的是模式缓冲区,而保持缓冲区是另一块内存空间, sed 的一些编辑命令可以对保 持缓冲区进行处理,并与模式缓冲区的内容互换。

java 复制代码
[root@localhost xj]# cat test.log 
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
last line!
[root@localhost xj]# ^C
[root@localhost xj]# sed -e '/sshd/h' -e '/avahi/x' -e '$G' test.log 
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
last line!
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin

三个-e 选项带上三个编辑命令组成,第1个-e 选项后的编辑命令将 sshd关键字的匹配行写入保持缓冲区(h 命令指将模式缓冲区内容复制到保持缓冲区);第 2个-e 选项后的编辑命令是遇见 sshd关键字的匹配行时,将保持缓冲区中的内容输出,并 将 avahi关键字的匹配行写入保持缓冲区,因此,结果中,原本 avahi行的位置 变为了sshd行 (x 命令是互换模式缓冲区和保持缓冲区的文本内容);第3个-e 选项后的 编辑命令表示到最后一行时(用$符号匹配),将保持缓冲区的内容追加到模式缓冲区中 (G 命令的意义),因此结果中,最后一行是 avahi行。

h 和 H、g 和 G 是两组对应的命令, h 和 H 命令是模式缓冲区内容替换保持缓冲区内容,不过h 是副本,即将保持缓冲区的旧内容覆盖掉,而H 是追加,即在保持缓冲区旧内容上增加新的内容; g 和 G 命令是保持缓冲区内容替换模式缓冲区内容,同样, g 是副本、 G 是追 加。

6.3 利用分号分隔多个编辑命令

java 复制代码
sed -e 's/s/S/' -e 's/m/M/' test.log
//等同于
sed 's/s/S/; s/m/M/' test.log
//二级命令提示符
[root@localhost xj]# sed '
> s/s/S/
> s/h/H/
> $d' test.log
SsHd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
avaHi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/Sbin/nologin
poStfix:x:89:89::/var/spool/postfix:/sbin/nologin
ntp:x:38:38::/etc/ntp:/Sbin/nologin
tcpdump:x:72:72::/:/Sbin/nologin
rHel:x:1000:1000:rhel:/home/rhel:/bin/baSh
db2inSt1:x:1001:901::/Home/db2inst1:/bin/bash
db2fenc1:x:1002:902::/Home/db2fenc1:/bin/baSh
db2aS:x:1003:903::/Home/db2as:/bin/bash
xj:x:808:809::/Home/xj1:/bin/baSh
$9999
.Sdfaj
相关推荐
小政同学2 分钟前
【NFS故障】共享的文件无法执行
linux·运维·服务器
不会写DN11 分钟前
受保护的海报图片读取方案 - 在不公开静态资源目录下如何获取静态资源
服务器
AI木马人22 分钟前
3.【Prompt工程实战】如何设计一个可复用的Prompt系统?(避免每次手写提示词)
linux·服务器·人工智能·深度学习·prompt
lwf00616422 分钟前
导数学习日记
学习·算法·机器学习
ch3nyuyu34 分钟前
Ubuntu(乌班图)基础指令
linux·运维·网络
qeen871 小时前
【编程日记】现阶段总结
学习
minglie11 小时前
gcc编译器汇总
linux
挽安学长1 小时前
保姆级教程,通过GACCode使用Claude Code Desktop!
运维·服务器
firstacui2 小时前
MGRE实验
运维·服务器·网络
白菜欣3 小时前
Linux —《开发三件套:gcc/g++、gdb、make/Makefile 全解析》
linux·运维