sed命令

-- TOC --

sed,stream editor的缩写,一行行处理输入的文本,按命令行控制参数进行处理。

sed is a “stream editor” that builds on top of the old ed editor.

sed是一个流编辑器,与文本编辑器不同的是,它不会打开一个视觉缓冲区,将文件的数据加载到其中进行处理。相反,它根据在终端输入的命令或脚本中的一系列命令,逐行对文件进行操作。

sed - stream editor for filtering and transforming text

Sed is a stream editor. A stream editor is used to perform basic text transformations on an input stream (a file or input from a pipeline). While in some ways similar to an editor which permits scripted edits (such as ed), sed works by making only one pass over the input(s), and is consequently more efficient. But it is sed's ability to filter text in a pipeline which particularly distinguishes it from other types of editors.

sed命令是面向“行”进行处理的,每一次处理一行内容。处理时,sed 会把要处理的行存储在缓冲区中,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。这个缓冲区被称为“模式空间”(pattern space)。

p & -n

p,print,打印,如果不加别的控制参数,输入文本的每一行会打印两次,一次是自动打印,一次是p控制的打印。加上-n参数(--quiet--silent),可以抑制自动打印:

$ sed -n 'p' tt
abcde
12345
cs.pynote.net
last line

只打印匹配正则表达式的行:

$ sed -n '/[a|.]/p' tt
abcde
cs.pynote.net
last line

/[a|.]/p这部分,两个/之间的是正则表达式(有a或有.,.在方括号中哦),最后是sed的控制参数。

要让sed的正则表达式发挥威力,需加上-E参数,extended regular expression,跟grep命令一样。

指定行:

$ sed -n '2p' tt
12345
$ sed -n '2,3p' tt
12345
cs.pynote.net

'1~Np',每N行选一行;

'$p',最后一行;

'2!p',反转,除了第2行的其它行;

找到了你需要的行,然后就可以在此基础上执行一些其它的sed编辑动作。

将文档空白行全部删除

删除后可以另外保存,也可以统计SLOC行数:

$ cat test.c | sed -n '/./p' > test2.c
$ cat test.c | sed -n '/./p' | wc -l

d

d,delete,删除,不是真的删除,只是将符合条件的行去掉,不自动输出:

$ sed 'd' tt
$ sed '2,3d' tt
abcde
last line
$ sed -E '/[0-9]+|last/d' tt
abcde
cs.pynote.net

s

s,substitution,做替换,这也许是sed工具最常用的命令。

下面这一组命令,第一个/后面的正则是用来选择行的,入选后采用s命令处理。

$ sed '/[0-9]/s/[0-9]/Y/' tt
abcde
Y2345
cs.pynote.net
last line
$ sed -n '/[0-9]/s/[0-9]/Y/p' tt
Y2345
$ sed -n '/[0-9]/s/[0-9]/Y/gp' tt
YYYYY
$ sed -n '/[0-9]/s/3/Y/p' tt
12Y45
$ sed -n '/[0-9]/s/3/&Y/p' tt
123Y45
$ sed -n '/[0-9]/s/[0-2]/&Y/gp' tt
1Y2Y345

p就是print,g是global,即全部替换(一行中的全部)的意思,语法与Vim的文本替换相似。&表示在后面追加(如果一行文本出现多次匹配pattern的地方,就一定要使用g参数)

更多的测试学习case,没有了s前的选择,默认就是所有行都会处理:

$ cat kk.txt
hello
world
this is line 3
final line
append line 1
end all
$ sed 's/world/cs.pynote.net/' kk.txt  # 可以直接用s替换
hello
cs.pynote.net
this is line 3
final line
append line 1
end all
$ sed 's/line/\U&/' kk.txt  # 将匹配的内容替换成大写,\L小写
hello
world
this is LINE 3
final LINE
append LINE 1
end all
$ sed 's/line/\U&/w sed.log' kk.txt  # 将匹配并替换后的行写入文件
hello
world
this is LINE 3
final LINE
append LINE 1
end all
$ cat sed.log
this is LINE 3
final LINE
append LINE 1

替换内容中如果有特殊符号,请使用转义\

s指令也可以使用逗号,作为分隔符,请看下面的case。

-e

e,expression,可支持多个sed控制表达式。

$ sed -n -e '/[0-9]/s/[0-2]/&Y/gp' -e '4p' tt
1Y2Y345
last line
$ sed -n -e '2p' -e '4p' tt
12345
last line

sed命令的s指令格式,可以使用逗号,带上多个-e参数的效果很不错:

$ echo '123abc123jkl' | sed -e 's,123,zzz,g' -e 's,abc,123,'
zzz123zzzjkl
$ echo '123abc123jkl' | sed -e 's,^123,zzz,' -e 's,zzz,yyy,'
yyyabc123jkl

上面第2个例子有点意思,可以看出-e参数是有顺序的。

a

a,append,追加行。

$ sed '/[0-9]/a number above' tt
abcde
12345
number above
cs.pynote.net
last line
$ sed '/cs/adomain' tt
abcde
12345
cs.pynote.net
domain
last line
$ sed '/cs/a\n\n\n\n' tt
abcde
12345
cs.pynote.net
n



last line

最好在a后面加个空格!

那个n不知道是怎么回事?

i

i,insert,在符合条件的行前面增加行。

y

不同于s整体替换,y逐字符替换是按照字符对应关系来的。

$ sed 'y/123456i/67890aj/' tt
abcde
67890
cs.pynote.net
last ljne

将12345替换成67890,6替换成a,但是输入文本中没有6,直接忽略,将i替换成j。

$ sed '1,2y/[a-z]/[A-Z]/' copy.txt
$ sed '1,2y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' copy.txt

对1,2行进行替换。

-i

inplace,直接修改文本。

前面介绍的控制参数,都不会修改输入本身,只是在输出之前,在缓存区修改而已,加上-i参数后,就是直接修改输入文件了!

$ sed -i -n '/./p' a.txt
$ sed -i 's/123/abc/g' b.txt

本文链接:https://cs.pynote.net/sf/linux/shell/202111282/

-- EOF --

-- MORE --