你真的懂 sed 命令吗?揭秘 Linux 高效文本处理的神器!

文摘   2024-11-04 09:00   广东  

点击上方【蓝字】关注博主

 在 Linux 系统中,文本处理是不可或缺的一部分。面对庞大的文本文件,如何高效地进行操作成为了一个关键问题。而 sed 命令正是解决这一问题的利器。它凭借简洁的语法、强大的功能和灵活的应用场景,成为 Linux 系统中不可或缺的文本处理工具。本文将带你深入了解 sed 命令,从基础语法到进阶技巧,并通过实际案例展示其在文本处理、数据分析、系统管理等方面的应用,让你掌握 sed 命令的精髓,成为 Linux 文本处理的高手!

01

前导 

本系列主要讲解Linux运行时命令,包括网络、磁盘、内存、CPU相关参数等,主要是为了分享怎么通过常见的 Linux 命令去排查相关问题。比如:

  1. 发现机器的CPU负荷比较高,那么怎么查到是哪个进程CPU占用率比较高?

  2. 磁盘IO的写入很频繁,怎么查到是哪个进程或线程对磁盘IO频繁的操作?

本系列就是分享诸如这类问题的排查技巧。注意,本系列的核心方向不是去讲解Linux的命令查找、显示当前目录等(比如ls、cat等)基础命令操作。本系列的重点分享内容包括:

  1. Linux基础命令和工具。

  2. CPU性能监控。

  3. 内存性能监控。

  4. 文件IO性能监控。

  5. 网络IO性能监控。

强烈推荐:Linux 大牛,Netflix 高级性能架构师 Brendan Gregg的博客http://www.brendangregg.com。《性能之巅》书籍就是他出版的,主要分为:CPU、内存、磁盘、网络四大块。



02

sed 命令基础 

sed 命令的基本语法:

sed [选项] '命令' [输入文件]
  • [选项]: 一些可选的选项,用于控制 sed 命令的行为。

  • ‘命令’: 要执行的命令,用单引号包裹。

  • [输入文件]: 要处理的输入文件。如果没有指定输入文件,则默认从标准输入读取数据。

常用选项:

选项描述示例
-n静默模式,只输出被修改的行sed -n 's/hello/world/g' file.txt
-e多个命令,用 -e 分隔sed -e 's/hello/world/g' -e '/^$/d' file.txt
-i直接修改原文件,慎用!sed -i 's/hello/world/g' file.txt
-r使用扩展正则表达式sed -r 's/[0-9]+/&00/g' file.txt

常用命令:

命令描述示例
a\在匹配行之后追加文本sed '/hello/a\This is a new line' file.txt
c\用新文本替换匹配行sed '/hello/c\This is a new line' file.txt
d删除匹配行sed '/hello/d' file.txt
i\在匹配行之前插入文本sed '/hello/i\This is a new line' file.txt
p打印匹配行sed -n '/hello/p' file.txt
s/旧文本/新文本/g替换匹配文本sed 's/hello/world/g' file.txt

这里要说明一下: 是命令的延续符,用于将命令分成多行。 g 表示全局替换,如果没有 g 则只替换每一行的第一个匹配项。

举例:

  • 替换文件中的所有 “hello” 为 “world”:

    sed 's/hello/world/g' file.txt
  • 删除文件中的所有空行:

    sed '/^$/d' file.txt
  • 在文件中的每行开头添加 “prefix-”:

    sed 's/^/prefix-/g' file.txt
  • 在文件中的每行结尾添加 “suffix”:

    sed '$a\suffix' file.txt
  • 将文件中的第一行替换为 “new line”:

    sed '1c\
    ew line'
    file.txt

需要注意的是:

  • sed 命令通常是按行处理的,它会逐行读取输入文件,并对每一行进行处理。

  • sed 命令的修改操作不会改变原始文件,除非使用 -i 选项。

  • sed 命令的命令和正则表达式都需要用单引号包裹,防止 shell 解释特殊字符。


03

sed 命令进阶 

正则表达式是 sed 命令的核心功能之一,它允许我们以灵活、强大的方式匹配特定文本。

sed 命令常用正则表达式:

符号描述示例
字符匹配

.匹配任意单个字符a.c 匹配 “abc”、“a1c” 等
*匹配前一个字符零次或多次ab*c 匹配 “ac”、“abc”、“abbc” 等
+匹配前一个字符一次或多次ab+c 匹配 “abc”、“abbc” 等,不匹配 “ac”
?匹配前一个字符零次或一次ab?c 匹配 “ac”、“abc” 等
[]匹配方括号内任意一个字符[abc] 匹配 “a”、“b” 或 “c”
[^...]匹配除方括号内字符以外的任意一个字符[^abc] 匹配除 “a”、“b” 或 “c” 之外的任意字符
\转义特殊字符\. 匹配点号
位置匹配

^匹配行首^abc 匹配以 “abc” 开头的行
$匹配行尾abc$ 匹配以 “abc” 结尾的行
\b匹配单词边界\bapple\b 匹配独立的单词 “apple”
分组匹配

(...)将匹配的文本分组(ab)c 将 “ab” 分组,可以通过 \1 引用
其他

|或运算符a|b 匹配 “a” 或 “b”

在 sed 命令中,正则表达式主要用于 s 命令的替换操作。

  • 示例: 将所有以 “http://” 开头的 URL 替换为 “https://”:

    sed 's/http:\/\//https:\/\//g' file.txt
  • 示例: 将所有数字替换为 “number”:

    sed 's/[0-9]+/number/g' file.txt
  • 示例: 将所有以 “Mr.” 开头的姓名替换为 “Mrs.”:

    sed 's/Mr\. \(.*\)/Mrs. \1/g' file.txt
    • \(...\) 分组匹配姓名。

    • \1 引用第一个分组匹配的文本,即姓名。

sed 命令还支持扩展正则表达式,使用 -r 选项开启。扩展正则表达式比基本正则表达式更强大,支持更复杂的匹配模式。

  • 示例: 匹配所有包含 “apple” 或 “banana” 的行:

    sed -r '/apple|banana/p' file.txt
  • 示例: 匹配所有以数字开头,以数字结尾的行:

    sed -r '/^[0-9]+.*[0-9]+$/p' file.txt

sed 命令支持多种地址定址方式,用于精准定位需要操作的文本。这些地址可以是行号、正则表达式、范围等等,使 sed 命令更加灵活和强大。

  1. 行号定址:指定操作的行范围;格式: [起始行号][,结束行号]。例如 1,5:表示操作第 1 行到第 5 行; 5:表示操作第 5 行; $,:表示操作从最后一行到文件末尾的所有行。

  2. 正则表达式定址:匹配符合正则表达式的行;格式: /[正则表达式]/

  3. 范围定址:操作从起始地址到结束地址的所有行。;格式: [起始地址],[结束地址]。例如: 1,/apple/: 操作从第 1 行到第一个包含 “apple” 的行;/^abc/,/def$/: 操作从以 “abc” 开头的行到以 “def” 结尾的行。

  4. 特殊地址

  • $ 最后一行。

  • ! 反选,操作除指定地址以外的所有行。

  • p 打印匹配行,常与 -n 选项配合使用,只输出匹配的行。

示例:

  • 将文件 test.txt 中第 3 行到第 5 行的所有 “apple” 替换为 “banana”:

    sed '3,5s/apple/banana/g' test.txt
  • 将文件 test.txt 中所有以 “http://” 开头的行替换为以 “https://” 开头的行:

    sed '/^http:\/\//s/http:\/\//https:\/\//g' test.txt
  • 将文件 test.txt 中除了第 1 行以外的所有行打印到屏幕:

    sed -n '1!p' test.txt


04

sed 命令的应用 

清理文本中的重复行:清理文件 data.txt 中的重复行,保留第一行。

sed '$!N; /^\(.*\)\
\1$/!P; D'
data.txt > data_unique.txt

说明:

  • $!N: 除了最后一行,读取下一行并追加到模式空间。

  • ^\(.*\)\ \1$: 匹配重复行,即第一行和第二行内容相同。

  • !P: 如果不匹配重复行,则打印模式空间第一行。

  • D: 删除模式空间第一行,继续循环处理。


将文本文件中的特定内容提取出来:从文件 log.txt 中提取所有以 “ERROR:” 开头的行。

sed '/^ERROR:/p' log.txt

将文本文件中的内容格式化:将文件 data.txt 中以空格分隔的数字,以逗号分隔。

sed 's/ /,/g' data.txt

统计文本文件中的特定单词数量:统计文件 text.txt 中 “apple” 出现的次数。

sed -n '/apple/p' text.txt | wc -l
05

实用技巧 

5.1、简单模式

一个简单的sed命令包含三个主要部分:参数、范围、操作。要操作的文件可以直接挂在命令行的最后。

说明:

  • -n 这个参数是--quiet或者--silent的意思。表明忽略执行过程的输出,只输出我们的结果即可。还有另外一个参数 :-i,使用此参数后,所有改动将在原文件上执行。你的输出将覆盖原文件。非常危险,一定要注意。

  • 范围:2,5 表示找到文件中2,3,4,5行的内容。这个范围的指定很有灵性,请看以下示例(请自行替换图中的范围部分)。5 选择第5行。2,5 选择2到5行,共4行。1~2 选择奇数行。2,5 选择2到5行,共4行。1~2 选择奇数行。2~2 选择偶数行。

  • 范围的选择还可以使用正则匹配。例如:

    # 选择出现void字样的行,以及后面的三行。
    /void/,+3
    # 选择以void开头的行,和出现mem字样行之间的数据。
    2\^void/,/mem/

为了直观,下面的命令对应上面的介绍,范围和操作之间是可以有空格的。

sed -n '5p' sed1.cpp

sed -n '2,5 p' sed1.cpp

sed -n '1~2 p' sed1.cpp

sed -n '2~2 p' sed1.cpp

sed -n '2,+3p' sed1.cpp

sed -n '2,$ p' sed1.cpp

sed -n '/void/,+3 p' sed1.cpp

sed -n '/^void/,/CLIENT_TYPE_FLAG_BOTH/p' sed1.cpp
sed -n '/^BroadcastPdu/,/CLIENT_TYPE_FLAG_BOTH/p' sed1.cpp
sed -n '/^void CImUserManager::BroadcastPdu/,/CLIENT_TYPE_FLAG_BOTH/p' sed1.cpp

最常用的操作是p,意思就是打印。比如,以下两个命令就是等同的:

cat file 
sed -n 'p' file

除了打印,还有以下操作对我们来说是常用的。

  • p 对匹配内容进行打印。

  • d 对匹配内容进行删除。这个时候就要去掉-n参数了,想想为什么?

  • w 将匹配内容写入到其他地方。

a,i,c等操作虽基本但使用少,依然拿一些命令来说明。

sed -n '2,5 p' sed2.cpp 
sed '2,5 d' sed2.cpp
sed -n '2,5 w output.txt' sed2.cpp

5.2、替换模式

以上是sed命令的常用匹配模式,但它还有一个强大的替换模式,意思就是查找替换其中的某些值,并输出结果。使用替换模式很少使用-n参数。

替换模式的参数有点多,但第一部分和第五部分都是可以省略的。替换后会将整个文本输出出来。
前半部分用来匹配一些范围,而后半部分执行替换的动作。

这里的命令是指s。也就是substitute的意思。

这里的范围和上面的范围语法类似。例如

/sys/,+3 选择出现sys字样的行,以及后面的三行。/^sys/,/mem/ 选择以sys开头的行,和出现mem字样行之间的数据。

具体命令为:

sed -n '/void/,+3 s/void/int/g' sed2.cpp
sed '/^void/,/CLIENT_TYPE_FLAG_BOTH/s/ImUser/User/g' sed2.cpp

查找部分会找到要被替换的字符串。这部分可以接受纯粹的字符串,也可以接受正则表达式。例如:

a 查找范围行中的字符串a。[a,b,c] 从范围行里查找字符串a或者b或者c。

命令类似:

sed 's/a/b/g' file
sed 's/[a,b,c]/<&>/g' file

替换: 是时候把找出的字符串给替换掉了。本部分的内容将替换查找匹配部分找到的内容。可惜的是,这部分不能使用正则。常用的就是精确替换。比如把 a替换成b。但也有高级功能。和java或者python的正则api类似,sed的替换同样有Matched Pattern的含义,同样可以得到Group,不深究。

常用的替位符,就是&& 号再重复一遍。当它用在替换字符串中的时候,代表的是原始的查找匹配数据。

[&] 表明将查找到的数据使用[]包围起来。“&” 表明将查找的数据使用””包围起来。

下面这条命令,将会把文件中的每一行,使用引号包围起来。

sed 's/.*/"&"/' file

flag 参数: 这些参数可以单个使用,也可以使用多个,仅介绍最常用的。

  • g 默认只匹配行中第一次出现的内容,加上g,就可以全文替换了。常用。

  • p :当使用了-n参数,p将仅输出匹配行内容。

  • w 和上面的w模式类似,但是它仅仅输出有变换的行。

  • i 这个参数比较重要,表示忽略大小写。

  • e 表示将输出的每一行,执行一个命令。不建议使用,可以使用xargs配合完成这种功能。

看两个命令的语法:

sed -n 's/a/b/gipw output.txt' file
sed 's/^/ls -la/e' file

更进一步学习:推荐https://github.com/Black-Gold/Learn/blob/1ee76ca2a9bbbbfe04850a1ccc9b9658e1eb39de/Linux_man_cn/sed.md。




06

总结

sed 命令是用来批量修改文本内容的,比如批量替换配置中的某个ip。sed 命令在处理时,会先读取一行,把当前处理的行存储在临时缓冲区中,处理完缓冲区中的内容后,打印到屏幕上。然后再读入下一行,执行下一个循环。不断的重复,直到文件末尾。

sed 命令作为一款功能强大、简洁高效的文本处理工具,在文本处理、数据分析、系统管理等各个领域都有广泛应用。学习和掌握 sed 命令,可以显著提高工作效率,简化工作流程。

命令格式1:sed 's/原字符串/新字符串/' 文件
命令格式2:sed 's/原字符串/新字符串/g' 文件

这两种命令格式的区别在于是否有个“g”。没有“g”表示只替换第一个匹配到的字符串,有“g”表示替换所有能匹配到的字符串,“g”可以认为是“global”(全局的)的缩写,没有“全局的”结尾就不要替换全部。

公众号: Lion 莱恩呀

微信号: 关注获取

扫码关注 了解更多内容

点个 在看 你最好看


Lion 莱恩呀
专注分享高性能服务器后台开发技术知识,涵盖多个领域,包括C/C++、Linux、网络协议、设计模式、中间件、云原生、数据库、分布式架构等。目标是通过理论与代码实践的结合,让世界上看似难以掌握的技术变得易于理解与掌握。
 最新文章