Sed 是一个流编辑器。流编辑器用于对输入执行基本的文本转换流。简单点:sed 是用于过滤和转换文本的流编辑器。
格式
sed [option] commond file
- option:参数选项。
- commond:需要对文件内每行内容所要的处理。
- file:处理的文件对象(输入流)。
sed 工作原理
sed 会将读取到的输入流存储到一个叫 “模式空间” 的缓冲区。然后 sed 会在缓冲区内进行循环处理,处理完成后,最后再将缓冲区里处理完成的内容进行输出。
详细步骤:
注意: 在整个处理的过程中,并不会对输入流本身做任何更改。
- sed 读取输入流的一行,并删除该行的尾随换行符,然后将其放置 “模式空间” 中处理。
- 执行 sed 命令处理时,会将命令文件中的地址与 “模式空间” 的字符进行匹配,然后在 “模式空间” 中与该地址匹配的部分执行关联的命令,从而更改 “模式空间” 的内容。
- 当达到匹配行的末尾时,会将删除的尾随换行符重新加回。接着处理下一行,与此往复,知道输入流的末尾。
参考资料
Sed 范围划分
在参阅了 sed, a stream editor 认为 sed 大致可以划分为两类:范围处理
、动作处理
。
在开始阐述前,觉得应该介绍一些较为常用的动作:
- a:在指定行后进行追加文本
- c:用文本替换更改行
- d:删除指定行的文本内容
- p:打印指定行内容
- r:读取指定的内容
- w:写入指定文件内容
此外,还需要掌握一个比较中重要命令:s
命令。
sed 's/regexp/replacement/flags' file
范围处理
可以通过指定以英文逗号(,)分隔的来指定地址的范围,一个地址范围从第一个地址匹配处开始的行,一直持续至第二个地址匹配处(包含)。
# -n: 只输出匹配的内容; '2,$p': 打印第2行至末尾的内容; file: 输入流
seq 10 | sed -n '2,$p'
如果第二个地址是正则表达式,那么检查结束匹配后,将从第一个地址匹配行后面的行开始,而范围将至少跨越 2 行。
seq 10 | sed -n '2,/[0-9]/p'
注意: 如果第二个地址是小于(等于)第一个地址的匹配的行,那么仅只会匹配第一个地址
seq 10 | sed -n '2,1p'
特殊双地址的表达形式
0,/regexp/
注意: 这是 0
地址唯一有意义的地方; 没有第0行,以任何其他方式给出 0 地址的命令都会出错。
在类似于 0,/regexp/
的地址规范中可以使用 0 行号,这样 sed 也可以尝试在第一个输入行中匹配 regexp。换句话说,0,/regexp/
类似于 1,/regexp/
,除了如果 addr2 匹配输入的第一行,/regexp/form 将认为它结束了范围,而 1,/regexp/form
将匹配其范围的开始,因此使范围跨度达到正则表达式的第二次出现。
seq 10 | sed -n '0,/[0-9]/p'
addr1,+N
匹配 addr1和 addr1之后的 n 行
seq 10 | sed -n '2,+2p'
addr1,~N
匹配 addr1 和 addr1 后面的行,直到输入行号为 n 的倍数的下一行。下面的命令打印从第 2 行开始,直到下一行是 4 的倍数(即第 4 行) :
seq 10 | sed -n '2,~4p'
动作处理
替换匹配的所有:
seq 15 | sed 's/2/4/'
如果需要执行替换的指定的行,那么可以使用地址进行指定:
# 只会替换第 2 行至 15 行中符合的行,而不会替换第 22 行的
seq 25 | sed '2,15s/2/4/'
地址除了可以根据内容的行号进行匹配,还可以包含正则表达式:
# 将 包含 2 的行中的 1 替换成 4
seq 20 | sed '/2/s/1/4/'
# 加上 ! 则是否定了匹配的意义,只选择与地址不匹配的行
seq 20 | sed '/2/!s/1/4/'
使用文件匹配
在 sed 中有一个选项参数是可以使用文件进行匹配的: -f
假设有一个 IP 列表文件
[root@ascmcs ~]# cat sc.txt
10.0.0.1
10.0.0.2
10.0.0.3
编写 sed 指定的替换文件
cat > sc.sed << EOF
s,10.0.0.1,10.0.0.4,g
s,10.0.0.2,10.0.0.5,g
s,10.0.0.3,10.0.0.6,g
EOF
开始替换
sed -i -f sc.sed sc.txt
插入文件内容
在前面 “范围划分” 的时候,就已经介绍了几个常用的动作,接下来详细介绍下 r
带来的体验
将 sc.sed 的内容插入至 sc.txt 匹配 10.0.0.4 的行的后面:
# 注意对文件所在位置的理解:在单引号内的是添加内容的文件,而在引号外面的是被添加内容的文件。
sed '/10.0.0.4/r sc.sed' sc.txt
控制文件内容写入指定的文件内
将 sc.sed 中的 5跟6 ip 写入至 sc.txt 文件内
sed '/10.0.0.[5-6]/w new.txt' sc.txt
特殊的动作处理
& 符号
&
可以实现在匹配的部分后面添加内容。
# 在所有以 1 开头的部分后面添加 xxx
seq 25 | sed 's/^1.*/&xxx/'
() 括号
在 sed 中,() 也被称为 “预存储技术”,也就是括号内的内容会被一次暂存起来,存储到 \N 里,在使用时则可以使用 /N
的形式来调用 (\1、\2 ……)
# 将匹配的1.*暂存起来,然后在匹配的部分后添加 '10010' 内容
seq 20 | sed 's/\(1.*\)/\110010/'
这里将三个内容进行了预存储:ascmcs (第一个)
、.* (中间的内容)
、ascmcs (最后一个)
# \1: 在第一个 ascmcs 后添加 10086
# \2: 输出匹配的中间所有内容
# \3: 在最后一个 ascmcs 后添加 10086
echo ascmcs ascmcs ascmcs ascmcs ascmcs | sed 's/\(ascmcs\)\(.*\)\(ascmcs\)/\110086\2\310086/'
更多
请参考:
- sed 手册
man sed
- sed, a stream editor