Linux的sed命令详解和实例

返回工具箱首页

在 Linux 和 Unix 系统中,sed(stream editor)是一款功能强大且灵活的文本处理工具。

1️⃣ 基本用法

sed 的基本语法如下:

sed [选项] '脚本/命令' 文件

1.1 🛠️ 常用选项

1.2 🛠️ 常用命令

1.3 🛠️ sed 命令 n,N,d,D,p,P,h,H,g,G,x

1、sed执行模板=sed '模式{命令1;命令2}' 即逐行读入模式空间,执行命令,最后输出打印出来。

2、先说下p和P,p打印当前模式空间内容,追加到默认输出之后,P打印当前模式空间开端至\n的内容,并追加到默认输出之前。sed并不对每行末尾\n进行处理,但是对N命令追加的行间\n进行处理,因为此时sed将两行看做一行。

2-1、n命令

n命令简单来说就是提前读取下一行,覆盖模型空间前一行(并没有删除,因此依然打印至标准输出),如果命令未执行成功(并非跳过:前端条件不匹配),则放弃之后的任何命令,并对新读取的内容,重头执行sed。

例子:

从aaa文件中取出偶数行

1
2
3
4
5
6
7
8
9
10
cat  aaa 
This is 1    
This is 2    
This is 3    
This is 4    
This is 5    
     
sed  -n  'n;p'  aaa          //-n 表示隐藏默认输出内容    
This is 2    
This is 4


注 释:读取This is 1,执行n命令,此时模式空间为This is 2,执行p,打印模式空间内容This is 2,之后读取 This is 3,执行n命令,此时模式空间为This is 4,执行p,打印模式空间内容This is 4,之后读取This is 5,执行n 命令,因为没有了,所以退出,并放弃p命令。

因此,最终打印出来的就是偶数行。

 

2-2、N命令

N命令简单来说就是追加下一行到模式空间,同时将两行看做一行,但是两行之间依然含有\n换行符,如果命令未执行成功(并非跳过:前端条件不匹配),则放弃之后任何命令,并对新读取的内容,重头执行sed。

例子:

从aaa文件中读取奇数行

1
2
3
4
5
6
7
8
9
10
11
cat  aaa   
This is 1   
This is 2   
This is 3   
This is 4   
This is 5   
                                                     
sed  -n  '$!N;P'  aaa            
This is 1   
This is 3   
This is 5

注释中1代表This is 1   2代表This is 2  以此类推

注释:读取1,$!条件满足(不是尾行),执行N命令,得出1\n2,执行P,打印得1,读取3,$!条件满足(不是尾行),执行N命令,得出3\n4,执行P,打印得3,读取5,$!条件不满足,跳过N,执行P,打印得5

 

2-3、d命令

d命令是删除当前模式空间内容(不在传至标准输出),并放弃之后的命令,并对新读取的内容,重头执行sed。

d命令例子

从aaa文件中取出奇数行

1
2
3
4
5
6
7
8
9
10
11
cat  aaa   
This is 1   
This is 2   
This is 3   
This is 4   
This is 5   
                                                           
sed  'n;d'  aaa           
This is 1   
This is 3   
This is 5

注释:读取1,执行n,得出2,执行d,删除2,得空,以此类推,读取3,执行n,得出4,执行d,删除4,得空,但是读取5时,因为n无法执行,所以d不执行。因无-n参数,故输出1\n3\n5

2-4、D命令

D命令是删除当前模式空间开端至\n的内容(不在传至标准输出),放弃之后的命令,但是对剩余模式空间重新执行sed。

D命令例子

从aaa文件中读取最后一行

1
2
3
4
5
6
7
8
9
cat  aaa   
This is 1   
This is 2   
This is 3   
This is 4   
This is 5   
                                                
sed  'N;D'  aaa           
This is 5

注释:读取1,执行N,得出1\n2,执行D,得出2,执行N,得出2\n3,执行D,得出3,依此类推,得出5,执行N,条件失败退出,因无-n参数,故输出5

 

2-5、y命令

y命令的作用在于字符转换

y命令例子:

将aaa文件内容大写

1
2
3
4
5
6
sed  'y/his/HIS/'  aaa  
THIS IS 1  
THIS IS 2  
THIS IS 3  
THIS IS 4  
THIS IS 5

此外,如果需要对某个字符串进行大小写转换,则可使用如下方法

1
2
3
4
5
6
7
8
9
10
11
12
13
cat  ddd   
This is a and a is 1   
This is b and b is 2   
This is c and c is 3   
This is d and d is 4   
This is e and e is 5   
    
sed  's/\b[a-z]\b/\u&/g'  ddd   
This is A and A is 1   
This is B and B is 2   
This is C and C is 3   
This is D and D is 4   
This is E and E is 5

2-6、h命令,H命令,g命令,G命令

h命令是将当前模式空间中内容覆盖至保持空间,H命令是将当前模式空间中的内容追加至保持空间

g命令是将当前保持空间中内容覆盖至模式空间,G命令是将当前保持空间中的内容追加至模式空间

命令例子:

将ddd文件中数字和字母互换,并将字母大写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cat  ddd. sed
h  
{  
s/.*is \(.*\) and .*/\1/  
y /abcde/ABCDE/
G  
s/\(.*\)\n\(.*is \).*\(and \).*\(is \)\(.*\)/\2\5 \3\5 \4\1/  
}  
                                           
sed  -f ddd. sed  ddd  
This is 1 and 1 is A  
This is 2 and 2 is B  
This is 3 and 3 is C  
This is 4 and 4 is D  
This is 5 and 5 is E

注释:读取1,执行h,复制到保持空间,执行s,模式空间得到匹配到的字母a,然后执行y,将a转成A,执行G,追加保持空间内容到模式空间,得

A\nThis is a and a is 1;执行s,重新排列,得出This is 1 and 1 is A;以此类推,得出结果。

这里需要注意的是匹配的内容中,空格一定要处理好,空格处理不对,会造成第二次s匹配错误,无法执行重新排列或排列错误

2-7、x命令

x命令是将当前保持空间和模式空间内容互换

 

2️⃣ 常用实例

2.1 🔄 替换文本 (s)

替换是 sed 最常用的功能之一。基本格式为:

sed 's/原文本/新文本/选项' 文件

示例:

# 将文件中的所有 foo 替换为 bar
sed 's/foo/bar/g' file.txt

# 只替换第一个 foo 为 bar
sed 's/foo/bar/' file.txt

# 只替换第2个 foo 为 bar
sed 's/foo/bar/2' file.txt

# 在原文件中直接替换 foo 为 bar
sed -i 's/foo/bar/g' file.txt

2.2 🗑️ 删除行 (d)

sed 可以根据条件删除行:

# 删除文件中的第2行
sed '2d' file.txt

# 删除文件中的第2到第4行
sed '2,4d' file.txt

# 删除所有包含 foo 的行
sed '/foo/d' file.txt

2.3 ➕ 插入和追加文本 (i 和 a)

在特定行前插入或在特定行后追加文本:

# 在第2行后追加一行 "This is a new line"
sed '2a\This is a new line' file.txt

# 在第2行前插入一行 "This is a new line"
sed '2i\This is a new line' file.txt

2.4 🔄 替换行 (c)

替换整行内容:

# 将第2行替换为 "This is a new line"
sed '2c\This is a new line' file.txt

# 将包含 foo 的行替换为 "This line contains foo"
sed '/foo/c\This line contains foo' file.txt

2.5 🖨️ 打印行 (p)

打印特定行:

# 打印文件中的第2行
sed -n '2p' file.txt

# 打印文件中的第2到第4行
sed -n '2,4p' file.txt

# 打印所有包含 foo 的行
sed -n '/foo/p' file.txt

2.6 🛠️ 多重编辑 (-e)

可以在一次 sed 调用中执行多个命令:

# 将第1行替换为 "First line",删除第2行
sed -e '1c\First line' -e '2d' file.txt

2.7 📜 使用脚本文件 (-f)

将多个 sed 命令写入脚本文件,并通过 -f 选项执行:

# 创建一个脚本文件 script.sed,内容如下:
# s/foo/bar/g
# 2d

# 使用脚本文件进行编辑
sed -f script.sed file.txt

3️⃣ 高级用法

3.1 🔄 替换文本并保留原始内容

可以使用 w 命令将修改后的内容写入新文件,同时保留原始文件:

# 将 foo 替换为 bar,同时将结果写入新文件
sed 's/foo/bar/g; w newfile.txt' file.txt

3.2 🗑️ 删除空白行和包含仅有空白字符的行

# 删除空白行
sed '/^$/d' file.txt

# 删除仅包含空白字符的行
sed '/^[[:space:]]*$/d' file.txt

3.3 📜 处理多行模式匹配

# 将包含 "start" 和 "end" 之间的所有行替换为 "replaced"
sed '/start/,/end/c\replaced' file.txt

3.4 🔄 使用正则表达式替换文本

# 将所有以数字开头的行中的 foo 替换为 bar
sed '/^[0-9]/s/foo/bar/g' file.txt

# 将所有形如 123-456-7890 的电话号码替换为 (123) 456-7890
sed -E 's/([0-9]{3})-([0-9]{3})-([0-9]{4})/(\1) \2-\3/g' file.txt

3.5 🔄 使用元字符处理文本

# 将每行的行首添加 "START: "
sed 's/^/START: /' file.txt

# 将每行的行尾添加 " :END"
sed 's/$/ :END/' file.txt

# 删除所有空行
sed '/^$/d' file.txt

# 删除所有以空格、制表符或换行符开头的行
sed '/^[ \t\n]/d' file.txt

3.6 🔄 替换并引用匹配的文本

# 将 foo 替换为 [foo]
sed 's/foo/[&]/g' file.txt

# 将形如 123-456-7890 的电话号码替换为 (123) 456-7890
sed -E 's/([0-9]{3})-([0-9]{3})-([0-9]{4})/(\1) \2-\3/g' file.txt

3.7 🖨️ 打印匹配模式的行

# 打印文件中的第2行
sed -n '2p' file.txt

# 打印文件中的第2到第4行
sed -n '2,4p' file.txt

# 打印所有包含 foo 的行
sed -n '/foo/p' file.txt

3.8 🗑️ 条件处理和多行操作

# 如果当前行包含 foo,则在当前行后追加 "Found foo"
sed '/foo/a\Found foo' file.txt

# 如果当前行包含 foo,则将其替换为 bar,否则将其替换为 baz
sed '/foo/{s/foo/bar/g;};/foo/!{s/$/baz/;}' file.txt

# 删除包含 foo 的行及其下一行
sed '/foo/{N;d;}' file.txt

# 在每两个连续的行合并成一行
sed 'N;s/\n/ /' file.txt

3.9 🗂️ 读取和写入文件

# 在每行后读取并插入文件 content.txt 的内容
sed 'r content.txt' file.txt

# 将所有包含 foo 的行写入 output.txt
sed -n '/foo/w output.txt' file.txt

3.10 🖥️ 在脚本中使用 sed

#!/bin/bash

# 示例:在脚本中使用 sed 进行替换
input="input.txt"
output="output.txt"

sed 's/foo/bar/g' "$input" > "$output"

# 示例:在脚本中使用多个 sed 命令
sed -e 's/foo/bar/g' -e '/baz/d' "$input" > "$output"

3.11 🌐 结合其他命令使用

3.11.1 使用管道将其他命令的输出传递给 sed

# 示例:将 ls 命令的输出传递给 sed,并将所有 .txt 文件替换为 .bak 文件
ls | sed 's/\.txt$/.bak/'

3.11.2 在脚本中结合使用 sed 和其他命令

#!/bin/bash

# 示例:将文件中的所有 foo 替换为 bar,并将结果传递给 grep 进行过滤
sed 's/foo/bar/g' file.txt | grep 'pattern'

3.12 📂 处理大文件

3.12.1 使用 sed 处理大文件时,可以结合其他工具提高效率

# 示例:使用 awk 和 sed 结合处理大文件,先用 awk 过滤,再用 sed 处理
awk '/pattern/' bigfile.txt | sed 's/foo/bar/g'

3.12.2 使用 sed 进行批量处理

# 示例:对目录中的所有文件进行批量处理,将所有 .txt 文件中的 foo 替换为 bar
for file in *.txt; do
  sed -i 's/foo/bar/g' "$file"
done

4️⃣ 综合示例

4.1 🗑️ 条件处理和多行操作

# 如果当前行包含 foo,则在当前行后追加 "Found foo"
sed '/foo/a\Found foo' file.txt

# 如果当前行包含 foo,则将其替换为 bar,否则将其替换为 baz
sed '/foo/{s/foo/bar/g;};/foo/!{s/$/baz/;}' file.txt

# 删除包含 foo 的行及其下一行
sed '/foo/{N;d;}' file.txt

# 将每两个连续的行合并成一行
sed 'N;s/\n/ /' file.txt

4.2 📂 处理大文件

4.2.1 使用 sed 处理大文件时,可以结合其他工具提高效率

# 示例:使用 awk 和 sed 结合处理大文件,先用 awk 过滤,再用 sed 处理
awk '/pattern/' bigfile.txt | sed 's/foo/bar/g'

4.2.2 使用 sed 进行批量处理

# 示例:对目录中的所有文件进行批量处理,将所有 .txt 文件中的 foo 替换为 bar
for file in *.txt; do
  sed -i 's/foo/bar/g' "$file"
done

4.3 🔄 高级替换和引用

4.3.1 使用 & 引用匹配的文本

# 将 foo 替换为 [foo]
sed 's/foo/[&]/g' file.txt

4.3.2 使用 \1, \2, … 引用捕获组

# 将形如 123-456-7890 的电话号码替换为 (123) 456-7890
sed -E 's/([0-9]{3})-([0-9]{3})-([0-9]{4})/(\1) \2-\3/g' file.txt

4.15 🌟 综合示例

4.15.1 处理多行模式

# 示例:将每两个连续的行合并成一行
sed 'N;s/\n/ /' file.txt

# 示例:删除包含 foo 的行及其前一行
sed '/foo/{x;d;}; x' file.txt

4.15.2 在特定行前后添加内容

# 在第5行前添加 "Start of section"
sed '5i\Start of section' file.txt

# 在第5行后添加 "End of section"
sed '5a\End of section' file.txt

4.15.3 删除文件中的特定模式及其后面的几行

# 删除包含 "pattern" 的行及其后面的两行
sed '/pattern/{N;N;d;}' file.txt

4.15.4 逆序文件中的行

# 使用 sed 和 tac(倒序输出)命令
tac file.txt | sed '1!G;h;$!d'

5️⃣ 使用 sed 进行文本分析

5.1 🧮 统计文件中包含特定模式的行数

# 统计文件中包含 "pattern" 的行数
grep -c 'pattern' file.txt

5.2 📊 统计文件中每个单词出现的次数

# 使用 tr、sort 和 uniq 命令统计每个单词出现的次数
tr -cs '[:alnum:]' '[\n*]' < file.txt | sort | uniq -c | sort -nr

# 使用 awk 统计每个单词出现的次数
awk '{for(i=1;i<=NF;i++) count[$i]++} END{for(word in count) print word, count[word]}' file.txt

5.3 🔍 查找并替换多行模式中的特定模式

# 示例:查找包含 "start" 和 "end" 之间的所有行,并将其中的 "foo" 替换为 "bar"
sed '/start/,/end/{s/foo/bar/g}' file.txt

5.4 🔍 查找并替换包含特定模式的行

# 示例:查找包含 "pattern" 的行,并将其中的 "foo" 替换为 "bar"
sed '/pattern/s/foo/bar/g' file.txt

5.5 🔍 查找并替换特定行范围内的模式

# 示例:查找第3行到第5行,并将其中的 "foo" 替换为 "bar"
sed '3,5{s/foo/bar/g}' file.txt

5.6 🔍 使用 sed 进行条件替换

# 示例:如果当前行包含 "pattern1",则将 "foo" 替换为 "bar"
sed '/pattern1/s/foo/bar/' file.txt

# 示例:如果当前行不包含 "pattern2",则将 "foo" 替换为 "baz"
sed '/pattern2/!s/foo/baz/' file.txt

6️⃣ 使用 sed 处理日志文件

6.1 🔍 查找并替换日志文件中的特定模式

# 示例:查找日志文件中的 "ERROR" 并将其替换为 "WARNING"
sed 's/ERROR/WARNING/g' logfile.log

6.2 🗑️ 删除日志文件中的特定日期范围内的日志

# 示例:删除日志文件中从 "2023-01-01" 到 "2023-01-31" 的所有日志
sed '/2023-01-01/,/2023-01-31/d' logfile.log

6.3 🔍 提取日志文件中的特定模式

# 示例:提取日志文件中包含 "ERROR" 的所有行
sed -n '/ERROR/p' logfile.log

6.4 🔄 替换日志文件中的时间戳格式

# 示例:将时间戳从 "YYYY-MM-DD HH:MM:SS" 格式替换为 "MM/DD/YYYY HH:MM:SS"
sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}:[0-9]{2}:[0-9]{2})/\2\/\3\/\1 \4/' logfile.log

6.5 🗂️ 将日志文件中的错误级别重新排序

# 示例:将日志文件中的 "ERROR", "WARNING", "INFO" 按照 "ERROR", "WARNING", "INFO" 的顺序重新排序
sed -E 's/(ERROR|WARNING|INFO)/\U&/g' logfile.log | sort -r

6.6 📊 统计日志文件中每种错误级别的次数

# 示例:统计日志文件中 "ERROR", "WARNING", "INFO" 出现的次数
grep -Eo 'ERROR|WARNING|INFO' logfile.log | sort | uniq -c

7️⃣ 使用 sed 进行文件格式转换

7.1 🔄 将文件中的所有大写字母转换为小写字母

sed 's/.*/\L&/' file.txt

7.2 🔄 将文件中的所有小写字母转换为大写字母

sed 's/.*/\U&/' file.txt

7.3 🔄 将制表符转换为空格

# 将所有制表符转换为四个空格
sed 's/\t/    /g' file.txt

7.4 🔄 将空格转换为制表符

# 将所有空格转换为制表符
sed 's/ \{1,\}/\t/g' file.txt

7.5 🔄 将 CSV 文件转换为 TSV 文件

# 将 CSV 文件中的逗号替换为制表符
sed 's/,/\t/g' file.csv

7.6 🔄 将 TSV 文件转换为 CSV 文件

# 将 TSV 文件中的制表符替换为逗号
sed 's/\t/,/g' file.tsv

8️⃣ 使用 sed 进行数据清洗

8.1 🗂️ 交换特定列的数据

# 使用 awk 交换 CSV 文件中的第2列和第4列
awk -F, '{temp=$2; $2=$4; $4=temp; OFS=","; print}' file.csv

9️⃣ 参考资料