数据流编辑器
sed [-cnrsu] [-i[suffix]] [-l n] [--follow-symlinks] [--posix] script [files]
sed [-cnrsu] [-e script] [-f script] [-i[suffix]] [-l n] [--follow-symlinks] [--posix] [files]
sed [--help] [--version]
sed是一个数据流编辑器,用于过滤和转换文本数据。sed采用一次性处理的方式,一边读取指定文件的输入数据流,一边施以基本的行编辑命令,实现文本数据的过滤与转换,把处理结果写到标准输出。
其中,files是欲编辑的文本文件的路径名。如果指定了多个输入文件,sed将会依次读取和编辑每一个文件。如果未指定输入文件,或指定的文件名为“-”,则读取标准输入。script是一组sed编辑命令,为保险起见,整个编辑命令前后应加引号。
作为脚本参数,编辑命令可以在命令行上直接提供,可以由“-e”选项指定,也可以取自“-f”选项指定的脚本文件。如果未指定“-e”或“-f”选项,sed把第一个非选项参数作为编辑命令脚本,把后续的其他参数作为输入文件解释和处理。
此外,“-e”和“-f”选项可以同时存在,也可以重复指定多个脚本文件。其中的所有编辑命令依序组合在一起,最终形成一个完整的sed编辑命令。
-c, --copy 在“-i”选项指定的模式中,采用复制而非重新命名的方式处理临时文件与输入文件。
-e script, --expression=script 把指定的编辑命令加到处理输入文件的编辑命令集合中。script可以含有多个sed编辑命令,每行一个,整个编辑命令前后加引号。
-f script, --file=script 把指定脚本文件script中的编辑命令加到处理输入文件的编辑命令集合中。脚本文件script含有sed编辑命令,每行一个。
-i[suffix], --in-place[=suffix] 编辑当前的输入文件,把处理结果写入新建的临时文件中(而非标准输出)。编辑完成之后,把临时文件重新命名为原始的输入文件(如果提供了扩展名suffix,在重新命名之前首先创建备份文件。注意,suffix与“-i”之间不能加空格)。指定“-i”选项也蕴含着同时指定了“-s”选项。
-l n, --line-length=n 指定sed的l(L的小写字母)命令使用的默认行宽。0意味着禁止把长行延续到下一行。如果未指定行宽,默认的行宽为70个字符位置。
-n, --quiet, --silent 压缩输出信息,仅显示sed编辑命令p明确指明的输出内容。
-r, --regexp-extended 使用扩展的正则表达式。
-s, --separate 通常,sed把多个输入文件看作一个连续的输入数据流,允许跨文件编辑。“-s”选项表示单独处理每一个文件。
-u, --unbuffered 尽可能使用最小的输入输出缓冲区,以便尽快看到处理后的结果。
--follow-symlinks 处理符号链接文件时使用其引用的文件。
--posix 禁止使用GNU的扩充特性。
sed脚本由一组sed编辑命令组成,每行一个编辑命令,每个编辑命令具有下列语法格式:
[address [, address]] command [ arguments ]
其中,address可以是一个十进制数值,表示输入数据的地址或行号,可以是一个美元符号,表示最后一行输入数据,也可以是一个正则表达式,表示匹配的数据行。command是sed编辑命令。arguments是编辑命令的参数。
在常规的操作过程中,sed采用循环的方式,逐行读取输入数据,然后把数据复制到模式空间(pattern space),再根据sed编辑命令的地址,依次施加匹配的编辑命令,最后,把模式空间的处理结果写到标准输出(除非指定了“-n”选项),删除模式空间。
此外,某些sed命令还使用收容空间(hold space)保存所有或部分模式空间,以便之后能够随时获取数据。
地址
执行sed命令时,地址可以省略,这意味着当前命令施加于所有的输入数据行。如果给定一个地址,表示sed命令仅作用于匹配指定地址的输入数据行。如果给定两个地址,sed命令可用于匹配指定地址范围内的所有输入数据行。
在单地址或双地址之后与sed编辑命令之前,可以插入一个感叹号“!”,表示相应的命令仅适用于不匹配指定地址或地址范围的其他数据行。
对于地址范围而言,有两件事情需要注意:addr1对应的数据行总是sed命令作用的对象,即使addr2小于addr1;如果addr2是一个正则表达式,sed也不会测试addr1对应的数据行。
单地址寻址
number 选择指定行号的数据行。
first~step 选择从first行开始每第step行的数据。例如,“sed -n 1~2p”将会显示输入数据流中的所有奇数行的数据。起始行first可以是0。
$ 选择最后一行。
/regexp/ 选择匹配正则表达式regexp的所有数据行。
\%regexp% 选择匹配正则表达式regexp的所有数据行。其中,%可以是任何字符。
注意,“/regexp/”与“\%regexp%”后面可以附加一个大写字母“I”,表示匹配时忽略大小写字母的差别。
双地址寻址
addr1,addr2 选择从第addr1行开始直至第addr2行的所有数据行。
addr1,+n 选择第addr1行与随后的n行数据。
addr1,~n 选择第addr1行直至某一输入数据行的行号是n的倍数之间的所有数据行。
0,/regexp/ “0,/regexp/”类似于“1,/regexp/”,都表示从第一个输入数据行开始匹配正则表达式。其差别是,在“0,/regexp/”的情况下,如果regexp 匹配第一行,则整个范围匹配结束。而在“1,/regexp/”的情况下,即使regexp 匹配第一行,也只是范围的开始,还需要继续检索,直至出现第二个匹配行才能构成一个范围。
0地址命令
: label 插入一个标号,供b和t命令跳转。
#comment 注释行,直至换行符为止。
} 终结一个{ }块。
0或单地址命令
= 显示当前的行号。
a\
text 追加文本数据text。在读取下一行输入数据前,把text写到标准输出。如果text包含多行数据,除了最后一行,每一行后面都要附加一个转义符号“\”。注意,i与c命令中的text也是如此处理。a(包括i和c)与“\”之间没有空格。
i\
text 插入文本数据text。把text写到标准输出。
q [exit-code] 停止任何数据处理动作,立即退出sed脚本(之前还需要输出当前的模式空间,除非禁用了自动输出功能)。
Q [exit-code] 停止任何数据处理动作,立即退出sed脚本。
r file 在读取下一行输入数据之前,读取指定文件中的全部数据,然后写到标准输出。
R file 在读取下一行输入数据之前,从指定的文件中读取一行数据,然后写到标准输出。每次调用R命令时,仅读取一行数据,输出一行数据。
双地址命令
{ 开始一个编辑命令块(以“}”结束)。
b label 跳转到指定的标号位置。如果省略了标号,跳转到脚本的最后位置。
t label 如果已经对最近读取的输入数据成功地执行了s替换命令,或执行了t或T命令,跳转到指定的标号位置。如果省略了标号,跳转到脚本的最后位置。
T label 如果没有对最近读取的输入数据成功地执行了s替换命令,或执行了t或T命令,跳转到指定的标号位置。如果省略了标号,跳转到脚本的最后位置。
c\
text 使用提供的数据text替换选择的行。删除模式空间,把text写到标准输出,开始下一轮处理。
d 删除模式空间,开始下一轮处理。
D 删除模式空间中的数据直至遇到第一个嵌入的换行符为止。开始下一轮处理,但跳过读取输入数据的步骤(如果模式空间仍存在数据)。
h 把模式空间中的数据复制到收容空间。
H 把模式空间中的数据追加到收容空间。
g 把收容空间中的数据复制到模式空间。
G 把收容空间中的数据追加到模式空间。
x 交换收容空间与模式空间中的数据内容。
l 以明显的形式,在标准输出上列出当前模式空间中的数据(不可打印的字符以转义的八进制数值显示,超长的数据行可延续到下一行)。
l width 以明显可视的形式,在标准输出上列出当前模式空间中的数据(不可打印的字符以转义的八进制数值显示,以指定的行宽为准,超长的数据行可延续到下一行)。
n 读取下一行输入数据,把数据复制到模式空间。
N 读取下一行输入数据,把数据追加到模式空间。
p 显示当前的模式空间。
P 显示当前模式空间中的数据直至遇到第一个嵌入的换行符。
s/re/sub/[flag] 使用正则表达式re匹配模式空间,如果成功,使用sub替换匹配的部分。sub中可以包含特殊字符“&”,引用模式空间中的匹配部分,也可以包含特殊的转义字符“\1”至“\9”,引用匹配正则表达式re中相应子表达式匹配的部分。flag是选用的标志,可以是下列常用的一个或多个标志,用于限定替换动作:
g 表示替换匹配指定表达式的所有字符串,而不是仅替换第一个匹配者。
n n是一个数字,表示仅替换第n个匹配指定表达式的字符串。
p 如果替换发生,显示替换后的结果。
w file 如果替换发生,把替换后的结果写入指定的文件。
I(或i) 在执行模式匹配时,忽略大小写字母的差异。
w file 把当前的模式空间写到指定的文件中。
W file 把当前模式空间的第一行写到指定的文件中。
y/src/dest/ 把模式空间中匹配src的字符映射为dest中的相应字符。
正则表达式
正则表达式是一种模式,用于描述检索对象中欲匹配的字符串。最简单的模式是由普通字符组成的字符串,用于匹配检索对象中的相应字符串。
正则表达式的威力来自模式中的特殊字符及其解释方式,能够实现复杂的匹配。下面是sed支持的正则表达式及其简单说明:
char 单个普通字符匹配自身。例如,abcdefg匹配字符串abcdefg。
* 匹配前一项0次或多次。前一项必须是一个普通字符、一个加了转义符号的特殊字符、一个句点“.”、一个组合的正则表达式或一个方括号表达式。例如,a*b匹配0个或多个a,最后跟随一个b。ap*le匹配ale或apple等。
\+ 类似于“*”,但匹配前一项1次或多次。例如,“a\+b\+”匹配一个或多个a,后跟随一个或多个b,其中ab是最短的匹配,其他可以是aab或abbb等。
\? 类似于“*”,但匹配前一项0次或1次。如a\?b匹配b或ab,script(\.sh)?匹配script或script.sh等。
\{m\} 类似于“*”,但恰好匹配m次。m是一个整数。例如,“[0-9]\{5\}”表示恰好匹配5位数字。
\{m,n\} 类似于“*”,但至少匹配前一项m次,不超过n次(包括m和n本身)。
\{m,\} 类似于“*”,但匹配前一项m次或m次以上。
\(re\) 把圆括号中的表达式re组合成一个整体,称作子表达式,用于后缀运算符,如“\(abcd\)*”表示检索0个或多个字符串abcd,而“abcd*”只能检索“abc”与后随的0个或多个字符“d”。此外,子表达式的一个重要用途是反向引用,参见“\digit”的说明。一个表达式中可以存在多个子表达式,子表达式从1开始编号。
. 匹配任何一个字符,包括换行符。例如,“.*”匹配字符串中的所有字符,或者说匹配任何一个字符串,包括空串。“.\+”匹配任何一个字符串,但每个字符串至少必须包含一个字符,即不匹配空串。
^ 匹配模式空间行首的空串,即匹配出现在模式空间行首的任何字符或字符串。例如,“^main.*(.*)”匹配一个位于行首的字符串main,紧随一对圆括号(“n”、“(”和“)”不需要紧连在一起)。“^#”匹配一个以“#”开始的位于行首的字符串,如“#include”。作为一个特殊字符,“^”也可以出现在正则表达式的前面,位于“\(”或“\|”之后。
$ 匹配模式空间行尾的空串。作为一个特殊字符,“$”也可以出现在正则表达式的后面,位于“\)”或“\|”之前。例如,“\\$”表示匹配任何以单个反斜线“\”(行延续符)结尾的数据行。“\.$”表示匹配任何以句点“.”结尾的数据行。
[list] 枚举的字符集合,表示匹配括号中的任何一个字符。例如,“[aeiou]”表示匹配所有的元音字母。在定义字符集合时,可以使用“char1-char2”的形式表示一个字符范围,如“[a-zA-Z0-9]”表示匹配任何ASCII字母或数字。此外,如果字符集合中出现特殊字符“$”、“*”、“.”、“[”或“\”(包括不在第一个字符位置的“^”),均作普通字符处理,例如,“[\*]”表示只匹配字符“\”或“*”,因为这里的“\”不是转义符号。此外,字符集合还可以容纳“[:class:]”、“[=a=]”或“[.ch.]”形式的字符类、等价类和排序符号等,如“[:alnum:]”表示所有的字母与数字。此外,如果POSIXLY_CORRECT环境变量没有设置,特殊的转义字符(如“\n”和“\t”等)也可以出现在方括号字符集合中。
[^list] 字符集合前的“^”符号意味着反其意而行之,表示不匹配方括号内的任何字符,而是匹配不在指定字符集合范围内的任何字符。例如,“[^[:space:]]\+”表示匹配由一个或多个非空白字符(空格或制表符)组成的字符串。
re1\|re2 匹配re1或re2。此外,利用子正则表达式还可以实现复杂的匹配。例如,“(E\|e)xit”表示匹配Exit或exit。
re1re2 匹配正则表达式re1与re2的连接。
\digit 反向引用(back reference),其中digit是一个数字,表示匹配正则表达式中第digit个子表达式“\(...\)”选择的字符串。例如,“^\(.*\)\n\1$”能够匹配两个等同的子串中间加换行符组成的字符串。
\char 匹配单个特殊字符,其中char是“$”、“*”、“.”、“[”、“\”或“^”等。例如,“\$”表示仅匹配由单个美元符号组成的字符串。
在正则表达式中,还可以使用下列转义字符,以匹配不可打印的特殊字符:
\a 匹配警示音。
\f 匹配换页符。
\n 匹配换行符。
\r 匹配回车字符。
\t 匹配制表符。
\v 匹配纵向制表符。
\cX 匹配Ctrl-X,X可以是任何字符。
\dXXX 匹配十进制ASCII编码表示的字符。
\oXXX 匹配八进制ASCII编码表示的字符。
\xXX 匹配十六进制ASCII编码表示的字符。
此外,sed正则表达式还支持下列特殊的字符类:
\w 匹配能够组成单字的任何字符,包括任何字母、数字或下画线。
\W 匹配非单字构成字符的任何字符,即除字母、数字和下画线之外的其他任何字符。
\b 匹配单字左右边缘的空串。例如,“\ba”能够匹配age或air等单词,“e\b”能够匹配same或come等单词。
\B 匹配单字非边缘字符位置的空串。例如,“\Bm”或“m\B”能够匹配same或come等单词。
\` 匹配模式空间起始字符位置的空串。类似于常规数据行匹配的“^”字符。
\’ 匹配模式空间结束字符位置的空串。类似于常规数据行匹配的“$”字符。
注意,正则表达式的匹配采用贪心方式。从左到右,从第一个匹配的字符开始,如果出现两个或更多的匹配者,最终选择的是最长者。
1. 把指定的设置追加到.bash_profile文件(为保险起见,保留一个备份.bash_profile.old)。
$ sed –i.old -e '$ a\ LANG=C; export LANG' .bash_profile $
2. 模拟“wc -l”命令,计数指定文件的行数。
$ sed -n '$=' /etc/profile 68 $
索引:A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z