Linux sed 命令:高效文本处理的神器!
一、前导:概述
本系列主要讲解Linux运行时命令,包括网络、磁盘、内存、CPU相关参数等,主要是为了分享怎么通过常见的 Linux 命令去排查相关问题。比如:
- 发现机器的CPU负荷比较高,那么怎么查到是哪个进程CPU占用率比较高?
- 磁盘IO的写入很频繁,怎么查到是哪个进程或线程对磁盘IO频繁的操作?
等等。
本系列就是分享诸如这类问题的排查技巧。注意,本系列的核心方向不是去讲解Linux的命令查找、显示当前目录等(比如ls、cat等)基础命令操作。本系列的重点分享内容包括:
- Linux基础命令和工具。
- CPU性能监控。
- 内存性能监控。
- 文件IO性能监控。
- 网络IO性能监控。
强烈推荐:Linux 大牛,Netflix 高级性能架构师 Brendan Gregg的博客http://www.brendangregg.com。《性能之巅》书籍就是他出版的,主要分为:CPU、内存、磁盘、网络四大块。
在 Linux 系统中,文本处理是不可或缺的一部分。面对庞大的文本文件,如何高效地进行操作成为了一个关键问题。而 sed
命令正是解决这一问题的利器。它凭借简洁的语法、强大的功能和灵活的应用场景,成为 Linux 系统中不可或缺的文本处理工具。本文将带你深入了解 sed
命令,从基础语法到进阶技巧,并通过实际案例展示其在文本处理、数据分析、系统管理等方面的应用,让你掌握 sed
命令的精髓,成为 Linux 文本处理的高手!
二、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 解释特殊字符。
三、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,5
:表示操作第 1 行到第 5 行;5
:表示操作第 5 行;$,
:表示操作从最后一行到文件末尾的所有行。 -
正则表达式定址:匹配符合正则表达式的行;格式:
/[正则表达式]/
。 -
范围定址:操作从起始地址到结束地址的所有行。;格式:
[起始地址],[结束地址]
。例如:1,/apple/
: 操作从第 1 行到第一个包含 “apple” 的行;/^abc/,/def$/
: 操作从以 “abc” 开头的行到以 “def” 结尾的行。 -
特殊地址:
$
: 最后一行。!
: 反选,操作除指定地址以外的所有行。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
四、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
五、实用技巧
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
六、 总结
sed
命令是用来批量修改文本内容的,比如批量替换配置中的某个ip。sed
命令在处理时,会先读取一行,把当前处理的行存储在临时缓冲区中,处理完缓冲区中的内容后,打印到屏幕上。然后再读入下一行,执行下一个循环。不断的重复,直到文件末尾。
sed
命令作为一款功能强大、简洁高效的文本处理工具,在文本处理、数据分析、系统管理等各个领域都有广泛应用。学习和掌握 sed
命令,可以显著提高工作效率,简化工作流程。
命令格式1:sed 's/原字符串/新字符串/' 文件
命令格式2:sed 's/原字符串/新字符串/g' 文件
这两种命令格式的区别在于是否有个“g”。没有“g”表示只替换第一个匹配到的字符串,有“g”表示替换所有能匹配到的字符串,“g”可以认为是“global”(全局的)的缩写,没有“全局的”结尾就不要替换全部。