Sed 的一些用例

这篇笔记是一两年前写的,但是是logseq的形式,现在把neng出来。

#snippet/shell 使用 sed 使用正则进行文件内容替换

sed,即stream editor,流编辑器,它一行一行读取文件或流,进行删除,编辑或查询(这个还是请grep来),然后再把操作后的内容打印出来或写回去。sed命令极度依赖正则。编写时注意——sed操作的始终是每一

sed命令的一般格式为:

1
sed [各种参数] <sed脚本> [输入文件,可以有多个]

示例

示例为先,但有几点需要特别注意:

  • 注意下面的操作除非加了-i,否则不会真正操作文件
  • 注意sed默认使用的正则功能是不全的,需要-E命令让它使用扩展正则语法
  • 注意所有带参数的命令,它的终结标志都是且只能是换行符,任意转义都是无效的,所以单行sed大多只能用无参命令,只有最后一个命令能用有参的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# 测试文件
cat > data <<EOF
wtf man
EOF

cat > test.txt <<EOF
apple rabbit roach
orange
hello, "orange", orange!
EOF

# 重复每一行(对每一行执行p命令,同时标准输出又会打一次)
sed 'p' test.txt

# 原文件内容(-n命令抑制默认输出,p命令再打印)
sed -n 'p' test.txt

# 筛选匹配orange的行(sed并非设计来做筛选操作的,所以它没有提供直接根据正则去筛选行的操作)
sed -n '/orange/p' test.txt

# 筛选匹配orange的行,并打印它们两次
sed -n '/orange/{p; p}' test.txt

# 打印匹配orange的行的行号
sed -n '/orange/=' test.txt

# 打印不匹配orange的行
sed '/orange/d' test.txt

# 原地删除(-i会修改文件)不匹配orange的行,其中给源文件做个带bak后缀的备份(可选)
sed -i.bak '/orange/d' test.txt

# 在匹配apple行前(上一行)插入'hello'
sed '/apple/i hello' test.txt

# 在匹配apple行后(下一行)追加'hello'
sed '/apple/a hello' test.txt

# 将所有orange替换为peach(不加g命令的话只会替换一次
sed 's/orange/peach/g' test.txt

# 把匹配hello,"xxx"的部分替换为 xxx(注意这里要用-E)
sed -E 's/hello, "(.*?)"/\1/' test.txt

# 匹配orange的行后插入data文件内容
sed -E '/orange/r data' test.txt

# 匹配orange行写入到orange.txt文件中(但仍同时打印整个test.txt文件,除非加-n)
sed -E '/orange/w orange.txt' test.txt

# 对每一行,打印行号,然后另起一行打印内容
sed '=' test.txt

# 对每一行,打印行号:内容
sed '=' test.txt | sed 'N; s/\n/: /'

# 替换并展示替换前后结果区别(相当于是dry-run了)
sed '/orange/peach/g' test.txt | diff test.txt -

sed脚本形式类似perl的正则表达式,它主要分为两类——查询/oattern/ COMMAND,和替换s/oattern/result/option。查询正则后需要加特定命令,而替换正则后可以加perl的一些选项,如g全局,i忽略大小写;命令可以独立存在也可以从属于特定正则。

替换语法是sed常用的,而查询语法可以理解为,倘若该行满足 /pattern/,则执行后续命令。某些命令只能应用到查询上,如d删除整行。

命令之间可以顺序执行,顺序执行的多个命令按;分割,每一行会依序地往后处理,根据命令修改自己的内容(遇到查询则不修改自身,继续往后执行,最后输出自己(-n命令抑制最后的输出)。

命令也可以有条件地执行——可以让命令只有在行满足特定模式下才去执行操作,形式为/pattern/{<sed脚本,可嵌套>}

此外,sed增加了下面的命令:

  • p:打印整行
  • d:删除整行
  • i 插入文本:匹配行前插入文本(另起一行)
  • a 追加文本:匹配行后追加文本(另起一行)
  • r 待插入文件:在匹配的行后插入另一个文件的内容(另起一行)
  • w 待写入文件:将匹配行写入到另一个文件
  • N:把下一行也读进来供后续命令操作

sed命令有如下参数:

  • -n:抑制默认输出,sed默认行为是总会进行打印,无论是否做了任何操作或是否匹配给定它的正则,此时只有在脚本中使用p命令才能使之打印出来,该参数常用于做筛选操作
  • -i:原地操作文件
  • -E:使用扩展正则表达式
  • -s:指定如果文件之间应当是分离的而非连续,如果不指定该项,每个文件之间行号会是连续的而非从1开始

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 协议 ,转载请注明出处!