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
相关推荐
小小洋洋37 分钟前
BLE MESH学习1-基于沁恒CH582学习
学习
韩楚风1 小时前
【linux 多进程并发】linux进程状态与生命周期各阶段转换,进程状态查看分析,助力高性能优化
linux·服务器·性能优化·架构·gnu
陈苏同学1 小时前
4. 将pycharm本地项目同步到(Linux)服务器上——深度学习·科研实践·从0到1
linux·服务器·ide·人工智能·python·深度学习·pycharm
Ambition_LAO1 小时前
解决:进入 WSL(Windows Subsystem for Linux)以及将 PyCharm 2024 连接到 WSL
linux·pycharm
Pythonliu71 小时前
茴香豆 + Qwen-7B-Chat-Int8
linux·运维·服务器
你疯了抱抱我1 小时前
【RockyLinux 9.4】安装 NVIDIA 驱动,改变分辨率,避坑版本。(CentOS 系列也能用)
linux·运维·centos
追风赶月、1 小时前
【Linux】进程地址空间(初步了解)
linux
栎栎学编程1 小时前
Linux中环境变量
linux
我是哈哈hh2 小时前
专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结
服务器·数据结构·c++·算法·机器学习·深度优先·剪枝
郭二哈2 小时前
C++——模板进阶、继承
java·服务器·c++