原文链接
sed 手册阅读笔记摘要sed 手册本身不太适合初学者,我在看的过程中加了一些 自己的注释和一些例子,帮助理解,如有偏差或错误,请指出,多谢。目录1. sed的工作原理
2. sed中如何选择特定的行
3. sed的命令行选项
4. sed命令
1. sed的工作原理sed维护两个缓冲区,pattern space和 hold space,命令开始执行之前都为空。pattern space缓冲区用于临时保存每次读取的一行的内容,大部分的 匹配和替换等等操作都是针对pattern space中的内容进行的,因此不会对输 入文件有任何影响;而hold space则作为后备缓冲区使用。sed针对输入中的每一行都会执行一个系列命令:首先,从标准输入流 读取一行,移除换行符,然后存入pattern space中,接着执行指定的命令。 每个命令都有一个可选的地址(也可能是一个正则表达式匹配),这个地址作 为一个执行前的测试,指定了需要对那些行进行操作。当前行只有匹配的情 况下才会执行命令。当指定所有的命令都执行完了之后,sed默认会将pattern space中的 内容打印到标准输出中,如果指定了-n选项,则会禁止这种默认的打印行为。 如果读取本行时移除了行尾的换行符,则在打印了pattern space中的内容后 会再打印一个换行符。这样针对本行的操作就完成了,然后sed会读取下一行 的内容,再次执行相同的操作。非指定了一些特殊的命令(例如D命令),否则pattern space中的内容 会在处理完一行之后删除,但hold space中的内容在处理完每一行时不会被 删除。例 1. 在匹配式样regex的行之前插入一空行sed '/regex/{x;p;x;}'x
Exchange the contents of the hold and pattern spaces.p
Print out the pattern space (to the standard output). This command is usually only used in conjunction with the `-n' command-line option.令执行过程如下:先读入一行,删除换行符,然后将其保存到 pattern space中,然后用/regex/正则表达式匹配pattern space中的内容, 如果匹配的话则执行后续的命令;如果不匹配则执行默认的打印pattern space中内容的操作,然后读取下一行。如果匹配的话,第一个x命令将pattern space和hold space中的内 容交换,由于此时hold space内容为空,实际的效果就是将pattern space的内容移动到hold space中,然后用p命令打印hold space的内容, 由于此时hold space为空,所以会打印一个空行,接着第二个x命令会又一 次交换pattern space和holdspace的内容,实际效果是原先读入的那一行 又会从hold space移动到patternspace中,最后打印此行内容。所以以上 命令的结果就是在每一个匹配/regex/的行之前插入一个空行。理解上述命令的关键在于当pattern space为空时,p命令会打印一 个空行,而不是一个空字符串。这涉及到sed的工作原理:sed会在读入一 行后,去掉行尾的换行符,然后将其内容存入pattern space中,打印时会 在最后加一个换行符。所以当pattern space为空时,p命令会先打印一个 空字符串,然后再打印一个换行符。2. sed中如何选择特定的行sed中有一些指定行范围的方法,用行号指定和用正则表达式指定,以 及两者结合起来指定。里面涉及到行号匹配的时候,如果指定了 -i或者-s选项的话则是相对于当前文 件。否则是相对于整个输入流。N
匹配输入中第N行。FIRST~STEP
从第FIRST行开始,每隔 STEP行选择一行。最终选择行的行号 等于 FIRST+(N*STEP) 。1~1选择所有行(在这里没什么意义),1~2选择奇数行,2~2选择偶 数行等等。$
匹配最后一行。/REGEXP/
选择所有匹配这个正则表达式的行。\%REGEXP%
同样是正则表达式匹配,上面的%可以换成任何字符,主要用 于匹配的内容包含大量需要转义的字符的情况下,例如匹配路径时。/REGEXP/I, \%REGEXP%I
同上,忽略大小写的正则表达式匹配。/REGEXP/M, \%REGEXP%M
同上,多行匹配。M表示multi-line。不使用M时,^和$只能 匹配pattern space的开始和结尾的位置,如果使用了M修饰符,且 pattern space中间有换行符的话,^还会匹配换行符后下一行开头 的位置,$还会匹配换行符和它之前的字符中间的位置。使用这个修饰符要注意,它不会改变sed每 次读取一行的默认行为。正因为sed的默认操作行为,一般情况下 pattern space中没有换行符。只有在pattern space中间有换行符 的情况下M修饰符才会有效果,可以通过N命令来达到这个目的。例 2. 模式匹配时M修饰符的作用~/pro/3.System_Config/tools/sed$ echo -e "a\nb\nc\nd" | sed -n 'N;s/^[a-z]$/X/p'
~/pro/3.System_Config/tools/sed$ echo -e "a\nb\nc\nd" | sed -n 'N;s/^[a-z]$/X/Mp'
X
b
X
d
~/pro/3.System_Config/tools/sed$sed首先将"a"读入pattern space,接着执行N命令,此时 pattern space中的内容为"a\nb",第一个sed命令没有使用M修饰符, /^[a-z]$/中的$不能匹配"\n"前面的位置,所以匹配失败,不执行 替换和打印命令。第二个sed命令使用了M修饰符,成功匹配,即 /^[a-z]$/匹配了"a"(其中的$匹配了"a"和"\n"中间的位置),将其 替换为"X",此时pattern space中的内容为"X\nb",然后用p命令打 印。注意由于在用N命令将"b"所在行加到pattern space的时候删去 了"b"所在行尾的换行符,所以在打印完"b"字符后sed会添加一个换 行符,就形成了结果中的前两行的输入,后续的执行过程相同。如果没有指定行号匹配条件,则所有的行都匹配。如果指定了行号 或者正则表达式,则只有与之匹配的行才选择。另外还可以用范围来选择特定的行,范围是用逗号分割的两个表达 式,表达式可以用上面的任意一种方式指定。如果范围内的第二个值小于 等于第一个值的话,那么只有与第一个值所匹配的单行匹配。Gnu sed 支持几种特殊的指定地址范围的方法:0,/REGEXP/
这种方式会使 /REGEXP/从第一行开始匹配,而常规 的 1,/REGEXP/ 则只能让/REGEXP/从第二行开始匹配。当/REGEXP/匹配第一行时,这 两种方式的差异就会体现出来。例 3. 比较 0,/REGEXP/ 和 1,/REGEXP/~/pro/3.System_Config/tools/sed$ cat a.txt
abcdef
xxx
yyy
abcdef
xxx
yyy
~/pro/3.System_Config/tools/sed$ sed -n '1,/abc/p' a.txt
abcdef
xxx
yyy
abcdef
~/pro/3.System_Config/tools/sed$ sed -n '0,/abc/p' a.txt
abcdefADDR1,+N
匹配从第ADDR1行以及以后 的N行。ADDR1,~N
匹配从第ADDR1行开始,直 到N的倍数行。例 4. 比较 ADDR1,+N 和 ADDR1,~N~/pro/3.System_Config/tools/sed$ cat c.txt
abcdef
xxx
yyy
zzz
~/pro/3.System_Config/tools/sed$ sed -n '1,+3p' c.txt
abcdef
xxx
yyy
zzz
~/pro/3.System_Config/tools/sed$ sed -n '1,~3p' c.txt
abcdef
xxx
yyy3. sed的命令行选项-n
默认情况下,sed会打印pattern space中的内容,这个选项禁止 sed的默认打印行为。-e SCRIPT
指定欲执行的命令,可以同时指定多个。sed会对pattern space中的内容依次执行每个-e选项指定的命令。~/pro/3.System_Config/tools/sed$ echo -e "abc\nbcd\ncde" | sed -n -e '/b/p' -e '/d/p'
abc
bcd
bcd
cde
可以看到"bcd"所在的行会被打印两次。-f SCRIPT-FILE
指定执行文件中的命令。-i [SUFFIX]
没有SUFFIX参数的时候,默认情况下sed不会修改输入的源文件, 会将内容打印到标准输出,使用了这个选项之后它会将输出保存到一 个临时文件,当所有命令执行完成之后,将临时文件重命名为输入的 源文件。如果指定了SUFFIX,会将输入的源文件作一个备份。当SUFFIX 里不包含星号时,备份的文件名为源文件名+SUFFIX;当SUFFIX里含一 个或者多个星号时,会将星号替换为源文件名,这种方式可以给备份 文件加上前缀,而不是简单地加一个后缀,甚至SUFFIX里可以包含路 径名,这样就可以将源文件备份到另一个文件夹里(前提是那个路径需 存在)。例 5. -i选项的值 SUFFIX不含星号的情况~/pro/3.System_Config/tools/sed$ ls *c*
c.txt
~/pro/3.System_Config/tools/sed$ cat c.txt
abcdef
xxx
yyy
zzz
~/pro/3.System_Config/tools/sed$ sed -ibackup 's/^.//g' c.txt
~/pro/3.System_Config/tools/sed$ ls *c*
c.txt c.txtbackup
~/pro/3.System_Config/tools/sed$ cat c.txt
bcdef
xx
yy
zz
~/pro/3.System_Config/tools/sed$ cat c.txtbackup
abcdef
xxx
yyy
zzz例 6. -i选项的值 SUFFIX包含星号的情况~/pro/3.System_Config/tools/sed$ cat c.txt
abcdef
xxx
yyy
zzz
~/pro/3.System_Config/tools/sed$ ls *c*
c.txt
~/pro/3.System_Config/tools/sed$ sed -ibackup* 's/^.//g' c.txt
~/pro/3.System_Config/tools/sed$ ls *c*
backupc.txt c.txt
~/pro/3.System_Config/tools/sed$ cat c.txt
bcdef
xx
yy
zz
~/pro/3.System_Config/tools/sed$ cat backupc.txt
abcdef
xxx
yyy
zzz-l N, --line-length=N
指定用l命令显示时的最长行的长度,如果文本大于这个长度会被 折行处理。折行时行尾会加一个反斜杠转义换行符。 N的长度默认为70。例 7. -l N选项本例中d.txt只包含一行内容,为100个字符a。~/pro/3.System_Config/tools/sed$ cat d.txt
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
~/pro/3.System_Config/tools/sed$ sed -n 'l' d.txt
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$
~/pro/3.System_Config/tools/sed$ sed -n -l 50 'l' d.txt
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aa$--posix
相对于POSIX sed, GNU sed 使用了一些扩展的功能,如果指定 这个选项会更加方便移植,但同时会禁用这些扩展功能。-b, --binary
将输入文件文件当作二进制文件来处理。在dos/windows平台上, 由于行分隔符是由CR和LF两个字符组成,如果不指定这个选项,sed也会 把这个两个字符的组合当成行分隔符。如果指定了这个选项,sed会将 LF当作换行符,这样CR就成了每行的最后一个字符。--follow-symlinks
是否跟随符号链接。这个选项只在支持符号链接的平台上存在, 并且只有同时使用了-i选项时才会起作用。如果输入 文件是到另一个文件符号链接,指定了这个选项会跟随符号链接。默认 情况下不跟随。-r, --regexp-extended
使用扩展的正则表达式。-s, --separate
默认情况下,sed 会将命令行指定的所有输入文件当作一个连续 的输入流来看待。这个选项会禁止这个特征,将文件独立对待,这会影 响某些匹配选项。例如$默认情况下会匹配整个输入流的最后一行,如果 指定了-s选项,$会匹配每个文件的最后一行。-u, --unbuffered
最小化输入和输出的缓冲区大小。如果输入是从类似于tail -f这 种管道取得的,这个选项会尽可能快地输出结果。4. sed命令#
注释q [EXIT-CODE]
这个命令只能用于单个地址的情况。q命令会让sed在打印完当前pattern space中的内容后立即退出, 如果没有用-n选项来禁止默认的打印行为的话。使 用可选的 [EXIT-CODE]代码 作为sed的退出码。d
删除当前pattern space中的内容并立即开始下一个循环,即 sed开始处理下一行。p
将当前pattern space中的内容打印到标准输入,这个选项一般 与-n选项一起使用。n
n命令会立即用读取的下一行的内容取代当前pattern space中的内容。 如果没有用-n选项来禁止默认的打印行为的话,n 命令会先打印完当前pattern space中的内容。如果到了输入的末尾, 即不能读取更多的内容,则sed立即退出,不执行n之后的命令。{ COMMAND }
{和}中间可以包含一组命令,用这种方式可以将这一组命令同 时作用到某一个地址上。s/REGEXP/REPLACEMENT/FLAGS
其中的/可以使用其它单个字符替换。/REPLACEMENT中可以使用一些特 殊的字符,这些字符有特殊的含义。\N
引用前面匹配的第N个捕 获性括号中的内容。L
将替换的内容都转换成小写字母,直到遇到\U或者\E。l
将下一个字符转换成小写字母。U
将替换的内容都转换成大写字母,直到遇到\L或者\E。E
停止\L或者\U的字母大小写转换。FLAGS为替换命令的修饰符。可 以包含一个或者多个以下字符。g
全局替换。默认为只替换第一个匹配的项。NUMBER
替换第NUMBER个匹配的项。U
将替换的内容都转换成大写字母,直到遇到\L或者\E。E
停止\L或者\U的字母大小写转换。p
w FILE-NAME
如果成功替换,将结果输出到 FILE-NAME文件中。e
这是GNU sed的一个扩展命令,如果成功执行了替换操作, 则替换的结果会作为一个shell命令来执行,然后将命令运行的 输出存入pattern space。~/pro/3.System_Config/tools/sed$ echo "date" | sed -n 's/^//ep'
Sat Oct 22 19:46:32 CST 2011
~/pro/3.System_Config/tools/sed$ cat g.txt
ls -l
~/pro/3.System_Config/tools/sed$ sed -n 's/^//ep' g.txt
total 156
-rw-r--r-- 1 forfun forfun 67 Oct 17 17:21 Makefile
-rw-r--r-- 1 forfun forfun 30 Oct 21 12:33 a.txt
......
-rw-r--r-- 1 forfun forfun 22598 Oct 22 19:49 sed.xml
-rw-r--r-- 1 forfun forfun 19550 Oct 21 15:10 sed.xml~
-rw-r--r-- 1 forfun forfun 35130 Oct 8 15:05 sed1line.txt
~$ echo "xxx12yyy" | sed -n -r 's/(.*?)([0-9]+)(.*?)/echo \1; echo \2+1|bc; echo \3/e; s/\n//gp'
xxx13yyy
I, i
忽略大小写。M, m
即匹配多行,与行匹配的M修饰符作用相同,见M修饰符。y
~/pro/3.System_Config/tools/sed$ echo "abc" | sed 'y/ab/AB/'
ABc
a\ TEXT
~/pro/3.System_Config/tools/sed$ echo -e "a\nb\nc" | sed '1,2a\
> xxx'
a
xxx
b
xxx
c
i\ TEXT
~/pro/3.System_Config/tools/sed$ echo -e "a\nb\nc" | sed '1,2i\
> yyy'
yyy
a
yyy
b
c
c\ TEXT
~/pro/3.System_Config/tools/sed$ echo -e "a\nb\nc" | sed '1,2c\
> zzz'
zzz
c
~/pro/3.System_Config/tools/sed$ echo -e "a\nb\nc" | sed '1,2='
1
a
2
b
c
=
~/pro/3.System_Config/tools/sed$ echo -e "a\nb\nc" | sed '1,2='
1
a
2
b
c
l N
~/pro/3.System_Config/tools/sed$ echo -e "\t\b"~/pro/3.System_Config/tools/sed$ echo -e "\t\b" | sed 'l'
\t\b$~/pro/3.System_Config/tools/sed$ cat d.txt
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
~/pro/3.System_Config/tools/sed$ sed -n 'l 40' d.txt
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaa$
r FILENAME
~/pro/3.System_Config/tools/sed$ cat c.txt
abcdef
xxx
yyy
zzz
~/pro/3.System_Config/tools/sed$ echo -e "a\nb\nc" | sed '1,2r c.txt'
a
abcdef
xxx
yyy
zzz
b
abcdef
xxx
yyy
zzz
c
w FILENAME
~/pro/3.System_Config/tools/sed$ echo -e "a\nb\nc" | sed '1,2w h.txt'
a
b
c
~/pro/3.System_Config/tools/sed$ cat h.txt
a
b
D
~/pro/3.System_Config/tools/sed$ cat i.txt
abc
123
def456
ghi
~/pro/3.System_Config/tools/sed$ sed '/[a-z]/D' i.txt
123
NP
~/pro/3.System_Config/tools/sed$ echo -e "a\nb\nc\nd" | sed 'N;P'
a
a
b
c
c
d
转载于:https://www.cnblogs.com/happydpc/archive/2012/08/18/sed.html