linux: sed

http://sed.sourceforge.net/

 

SED(1)                 User Commands                SED(1)



NAME
       sed - stream editor for filtering and transforming text

SYNOPSIS
       sed [OPTION]... {script-only-if-no-other-script} [input-file]...

DESCRIPTION
       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.

       -n, --quiet, --silent

          suppress automatic printing of pattern space

       -e script, --expression=script

          add the script to the commands to be executed

       -f script-file, --file=script-file

          add the contents of script-file to the commands to be executed

       --follow-symlinks

          follow symlinks when processing in place

       -i[SUFFIX], --in-place[=SUFFIX]

          edit files in place (makes backup if extension supplied)

       -l N, --line-length=N

          specify the desired line-wrap length for the ‘l’ command

       --posix

          disable all GNU extensions.

       -r, --regexp-extended

          use extended regular expressions in the script.

       -s, --separate

          consider    files  as  separate rather than as a single continuous
          long stream.

       -u, --unbuffered

          load minimal amounts of data from the input files and flush  the
          output buffers more often

       --help display this help and exit

       --version
          output version information and exit

       If  no  -e, --expression, -f, or --file option is given, then the first
       non-option argument is taken as    the  sed  script  to  interpret.   All
       remaining  arguments  are  names     of input files; if no input files are
       specified, then the standard input is read.

       GNU sed home page:  <http://www.gnu.org/software/sed/>.     General  help
       using  GNU software: <http://www.gnu.org/gethelp/>.  E-mail bug reports
       to: <bug-gnu-utils@gnu.org>.  Be sure to include the word ‘‘sed’’ some-
       where in the ‘‘Subject:’’ field.

COMMAND SYNOPSIS
       This is just a brief synopsis of sed commands to serve as a reminder to
       those who already know sed; other documentation (such  as  the  texinfo
       document) must be consulted for fuller descriptions.

   Zero-address ‘‘commands’’
       : label
          Label for b and t commands.

       #comment
          The  comment  extends until the next newline (or the end of a -e
          script fragment).

       }      The closing bracket of a { } block.

   Zero- or One- address commands
       =      Print the current line number.

       a \

       text   Append text, which has each embedded newline preceded by a back-
          slash.

       i \

       text   Insert text, which has each embedded newline preceded by a back-
          slash.

       q [exit-code]
          Immediately quit the sed    script    without     processing  any  more
          input,  except  that  if    auto-print is not disabled the current
          pattern space will be printed.  The exit code argument is a  GNU
          extension.

       Q [exit-code]
          Immediately  quit     the  sed  script  without processing any more
          input.  This is a GNU extension.

       r filename
          Append text read from filename.

       R filename
          Append a line read from filename.     Each invocation of  the  com-
          mand reads a line from the file.    This is a GNU extension.

   Commands which accept address ranges
       {      Begin a block of commands (end with a }).

       b label
          Branch to label; if label is omitted, branch to end of script.

       t label
          If  a  s///  has    done  a successful substitution since the last
          input line was read and since the last  t     or  T    command,  then
          branch to label; if label is omitted, branch to end of script.

       T label
          If  no  s///  has     done a successful substitution since the last
          input line was read and since the last  t     or  T    command,  then
          branch  to  label; if label is omitted, branch to end of script.
          This is a GNU extension.

       c \

       text   Replace the selected lines with text, which  has    each  embedded
          newline preceded by a backslash.

       d      Delete pattern space.  Start next cycle.

       D      Delete  up  to  the first embedded newline in the pattern space.
          Start next cycle, but skip reading from the input     if  there  is
          still data in the pattern space.

       h H    Copy/append pattern space to hold space.

       g G    Copy/append hold space to pattern space.

       x      Exchange the contents of the hold and pattern spaces.

       l      List out the current line in a ‘‘visually unambiguous’’ form.

       l width
          List  out     the  current line in a ‘‘visually unambiguous’’ form,
          breaking it at width characters.    This is a GNU extension.

       n N    Read/append the next line of input into the pattern space.

       p      Print the current pattern space.

       P      Print up to the first embedded newline of     the  current  pattern
          space.

       s/regexp/replacement/
          Attempt  to match regexp against the pattern space.  If success-
          ful,  replace  that  portion  matched  with  replacement.       The
          replacement may contain the special character & to refer to that
          portion of the pattern space  which  matched,  and  the  special
          escapes  \1  through  \9    to refer to the corresponding matching
          sub-expressions in the regexp.

       w filename
          Write the current pattern space to filename.

       W filename
          Write the first line of the current pattern space     to  filename.
          This is a GNU extension.

       y/source/dest/
          Transliterate  the  characters in the pattern space which appear
          in source to the corresponding character in dest.

Addresses
       Sed commands can be given with no addresses, in which case the  command
       will  be     executed for all input lines; with one address, in which case
       the command will only be executed for  input  lines  which  match  that
       address;     or with two addresses, in which case the command will be exe-
       cuted for all input lines which match  the  inclusive  range  of     lines
       starting     from  the first address and continuing to the second address.
       Three things to note about address ranges: the  syntax  is  addr1,addr2
       (i.e.,  the  addresses  are separated by a comma); the line which addr1
       matched will always be accepted, even if addr2 selects an earlier line;
       and  if    addr2 is a regexp, it will not be tested against the line that
       addr1 matched.

       After the address (or address-range), and before the command, a !   may
       be inserted, which specifies that the command shall only be executed if
       the address (or address-range) does not match.

       The following address types are supported:

       number Match only the specified line number.

       first~step
          Match every step’th line starting with line first.  For example,
          ‘‘sed  -n     1~2p’’     will  print all the odd-numbered lines in the
          input stream, and the address 2~5 will match every  fifth     line,
          starting    with the second.  first can be zero; in this case, sed
          operates as if it were equal to step.  (This is an extension.)

       $      Match the last line.

       /regexp/
          Match lines matching the regular expression regexp.

       \cregexpc
          Match lines matching the regular expression regexp.  The    c  may
          be any character.

       GNU sed also supports some special 2-address forms:

       0,addr2
          Start  out  in  "matched    first  address"     state, until addr2 is
          found.  This is similar to 1,addr2, except that if addr2 matches
          the very first line of input the 0,addr2 form will be at the end
          of its range, whereas the 1,addr2 form  will  still  be  at  the
          beginning of its range.  This works only when addr2 is a regular
          expression.

       addr1,+N
          Will match addr1 and the N lines following addr1.

       addr1,~N
          Will match addr1 and the lines following addr1  until  the  next
          line whose input line number is a multiple of N.

REGULAR EXPRESSIONS
       POSIX.2 BREs should be supported, but they aren’t completely because of
       performance problems.  The \n sequence in a regular expression  matches
       the newline character, and similarly for \a, \t, and other sequences.

BUGS
       E-mail  bug  reports  to     bonzini@gnu.org.  Be sure to include the word
       ‘‘sed’’ somewhere in the ‘‘Subject:’’ field.  Also, please include  the
       output of ‘‘sed --version’’ in the body of your report if at all possi-
       ble.

COPYRIGHT
       Copyright © 2009 Free Software Foundation, Inc.
       This is free software; see the source for copying conditions.  There is
       NO  warranty;  not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
       PURPOSE, to the extent permitted by law.

       GNU sed home page:  <http://www.gnu.org/software/sed/>.     General  help
       using  GNU software: <http://www.gnu.org/gethelp/>.  E-mail bug reports
       to: <bug-gnu-utils@gnu.org>.  Be sure to include the word ‘‘sed’’ some-
       where in the ‘‘Subject:’’ field.

SEE ALSO
       awk(1),    ed(1),    grep(1),  tr(1),  perlre(1),  sed.info, any of various
       books on sed, the sed FAQ
       (http://sed.sf.net/grabbag/tutorials/sedfaq.txt),
       http://sed.sf.net/grabbag/.

       The full documentation for sed is maintained as a Texinfo manual.  If
       the info and sed programs are properly installed at your site, the com-
       mand

          info sed

       should give you access to the complete manual.



sed version 4.2.1         October 2009                SED(1)

1.简介
sed是非交互式的编辑器。默认情况下它不会修改文件,但可使用-i参数在原文件修改,或者使用shell重定向来保存结果。默认情况下,所有的输出行都被打印到屏幕上。
sed编辑器逐行处理文件(或输入),并将结果发送到屏幕。具体过程如下:首先sed把当前正在处理的行保存在一个临时缓存区中(也称为模式空 间),然后处理临时缓冲区中的行,完成后把该行发送到屏幕上。sed每处理完一行就将其从临时缓冲区删除,然后将下一行读入,进行处理和显示。处理完输入 文件的最后一行后,sed便结束运行。sed把每一行都存在临时缓冲区中,对这个副本进行编辑,所以不会修改原文件。
 
2.定址
定址用于决定对哪些行进行编辑。地址的形式可以是数字、正则表达式、或二者的结合。如果没有指定地址,sed将处理输入文件的所有行。
 
地址是一个数字,则表示行号;是“$"符号,则表示最后一行。例如: 

sed -n '3p' datafile
只打印第三行

 

 只显示指定行范围的文件内容,例如:

# 只查看文件的第100行到第200行
sed -n '100,200p' mysql_slow_query.log

 

地址是逗号分隔的,那么需要处理的地址是这两行之间的范围(包括这两行在内)。范围可以用数字、正则表达式、或二者的组合表示。例如:

sed '2,5d' datafile
#删除第二到第五行
sed '/My/,/You/d' datafile
#删除包含"My"的行到包含"You"的行之间的行
sed '/My/,10d' datafile
#删除包含"My"的行到第十行的内容

 

 

3.命令与选项

sed命令告诉sed如何处理由地址指定的各输入行,如果没有指定地址则处理所有的输入行。

 

3.1 sed命令

 命令  功能
 a\

 在当前行后添加一行或多行。多行时除最后一行外,每行末尾需用“\”续行

 c\  用此符号后的新文本替换当前行中的文本。多行时除最后一行外,每行末尾需用"\"续行
 i\  在当前行之前插入文本。多行时除最后一行外,每行末尾需用"\"续行
 d  删除行
 h  把模式空间里的内容复制到暂存缓冲区
 H  把模式空间里的内容追加到暂存缓冲区
 g  把暂存缓冲区里的内容复制到模式空间,覆盖原有的内容
 G  把暂存缓冲区的内容追加到模式空间里,追加在原有内容的后面
 l  列出非打印字符
 p  打印行
 n  读入下一输入行,并从下一条命令而不是第一条命令开始对其的处理
 q  结束或退出sed
 r  从文件中读取输入行
 !  对所选行以外的所有行应用命令
 s  用一个字符串替换另一个
 g  在行内进行全局替换
   
 w  将所选的行写入文件
 x  交换暂存缓冲区与模式空间的内容
 y  将字符替换为另一字符(不能对正则表达式使用y命令)

 

3.2 sed选项

 选项  功能
 -e  进行多项编辑,即对输入行应用多条sed命令时使用
 -n  取消默认的输出
 -f  指定sed脚本的文件名
 
 
4.退出状态
sed不向grep一样,不管是否找到指定的模式,它的退出状态都是0。只有当命令存在语法错误时,sed的退出状态才不是0。
5.正则表达式元字符
 与grep一样,sed也支持特殊元字符,来进行模式查找、替换。不同的是,sed使用的正则表达式是括在斜杠线"/"之间的模式。
如果要把正则表达式分隔符"/"改为另一个字符,比如o,只要在这个字符前加一个反斜线,在字符后跟上正则表达式,再跟上这个字符即可。例如:sed -n '\o^Myop' datafile
 
 元字符  功能  示例
 ^  行首定位符  /^my/  匹配所有以my开头的行
 $  行尾定位符  /my$/  匹配所有以my结尾的行
 .  匹配除换行符以外的单个字符  /m..y/  匹配包含字母m,后跟两个任意字符,再跟字母y的行
 *  匹配零个或多个前导字符  /my*/  匹配包含字母m,后跟零个或多个y字母的行
 []  匹配指定字符组内的任一字符  /[Mm]y/  匹配包含My或my的行
 [^]  匹配不在指定字符组内的任一字符  /[^Mm]y/  匹配包含y,但y之前的那个字符不是M或m的行
 \(..\)  保存已匹配的字符  1,20s/\(you\)self/\1r/  标记元字符之间的模式,并将其保存为标签1,之后可以使用\1来引用它。最多可以定义9个标签,从左边开始编号,最左边的是第一个。此例中,对第1到第 20行进行处理,you被保存为标签1,如果发现youself,则替换为your。
 &  保存查找串以便在替换串中引用  s/my/**&**/  符号&代表查找串。my将被替换为**my**
 \<  词首定位符  /\<my/  匹配包含以my开头的单词的行
 \>  词尾定位符  /my\>/  匹配包含以my结尾的单词的行
 x\{m\}  连续m个x  /9\{5\}/ 匹配包含连续5个9的行
 x\{m,\}  至少m个x  /9\{5,\}/  匹配包含至少连续5个9的行
 x\{m,n\}  至少m个,但不超过n个x  /9\{5,7\}/  匹配包含连续5到7个9的行
 
6.范例
 
6.1 p命令
命令p用于显示模式空间的内容。默认情况下,sed把输入行打印在屏幕上,选项-n用于取消默认的打印操作。当选项-n和命令p同时出现时,sed可打印选定的内容。
 

sed '/my/p' datafile
#默认情况下,sed把所有输入行都打印在标准输出上。如果某行匹配模式my,p命令将把该行另外打印一遍。


sed -n '/my/p' datafile
#选项-n取消sed默认的打印,p命令把匹配模式my的行打印一遍。

 

6.2 d命令

命令d用于删除输入行。sed先将输入行从文件复制到模式空间里,然后对该行执行sed命令,最后将模式空间里的内容显示在屏幕上。如果发出的是命令d,当前模式空间里的输入行会被删除,不被显示。

sed '$d' datafile
#删除最后一行,其余的都被显示

sed '/my/d' datafile
#删除包含my的行,其余的都被显示

 

6.3 s命令

sed 's/^My/You/g' datafile
#命令末端的g表示在行内进行全局替换,也就是说如果某行出现多个My,所有的My都被替换为You。

sed -n '1,20s/My$/You/gp' datafile
#取消默认输出,处理1到20行里匹配以My结尾的行,把行内所有的My替换为You,并打印到屏幕上。

  

sed 's#My#Your#g' datafile
#紧跟在s命令后的字符就是查找串和替换串之间的分隔符。分隔符默认为正斜杠,但可以改变。无论什么字符(换行符、反斜线除外),只要紧跟s命令,就成了新的串分隔符。

 

6.4 e选项

-e是编辑命令,用于sed执行多个编辑任务的情况下。在下一行开始编辑前,所有的编辑动作将应用到模式缓冲区中的行上。

sed -e '1,10d' -e 's/My/Your/g' datafile

#选项-e用于进行多重编辑。第一重编辑删除第1-3行。第二重编辑将出现的所有My替换为Your。因为是逐行进行这两项编辑(即这两个命令都在模式空间的当前行上执行),所以编辑命令的顺序会影响结果。

 

6.5 r命令

r命令是读命令。sed使用该命令将一个文本文件中的内容加到当前文件的特定位置上。

sed '/My/r introduce.txt' datafile
#如果在文件datafile的某一行匹配到模式My,就在该行后读入文件introduce.txt的内容。如果出现My的行不止一行,则在出现My的各行后都读入introduce.txt文件的内容。

 
6.6 w命令

sed -n '/hrwang/w me.txt' datafile

 

6.7 a\ 命令

a\ 命令是追加命令,追加将添加新文本到文件中当前行(即读入模式缓冲区中的行)的后面。所追加的文本行位于sed命令的下方另起一行。如果要追加的内容超过一行,则每一行都必须以反斜线结束,最后一行除外。最后一行将以引号和文件名结束。

sed '/^hrwang/a\
>hrwang and mjfan are husband\
>and wife' datafile
#如果在datafile文件中发现匹配以hrwang开头的行,则在该行下面追加hrwang and mjfan are husband and wife

 

6.8 i\ 命令

i\ 命令是在当前行的前面插入新的文本。

 

6.9 c\ 命令

sed使用该命令将已有文本修改成新的文本。

 

6.10 n命令

sed使用该命令获取输入文件的下一行,并将其读入到模式缓冲区中,任何sed命令都将应用到匹配行紧接着的下一行上。

sed '/hrwang/{n;s/My/Your/;}' datafile

注:如果需要使用多条命令,或者需要在某个地址范围内嵌套地址,就必须用花括号将命令括起来,每行只写一条命令,或这用分号分割同一行中的多条命令。
 
6.11 y命令
该命令与UNIX/Linux中的tr命令类似,字符按照一对一的方式从左到右进行转换。例如,y/abc/ABC/将把所有小写的a转换成A,小写的b转换成B,小写的c转换成C。
 

sed '1,20y/hrwang12/HRWANG^$/' datafile
#将1到20行内,所有的小写hrwang转换成大写,将1转换成^,将2转换成$
#正则表达式元字符对y命令不起作用。与s命令的分隔符一样,斜线可以被替换成其它的字符。

 

6.12 q命令

q命令将导致sed程序退出,不再进行其它的处理。

sed '/hrwang/{s/hrwang/HRWANG/;q;}' datafile

 

6.13 h命令和g命令

#cat datafile

My name is hrwang.

Your name is mjfan.

hrwang is mjfan's husband.

mjfan is hrwang's wife.

  

sed -e '/hrwang/h' -e '$G' datafile

sed -e '/hrwang/H' -e '$G' datafile

#通过上面两条命令,你会发现h会把原来暂存缓冲区的内容清除,只保存最近一次执行h时保存进去的模式空间的内容。而H命令则把每次匹配hrwnag的行都追加保存在暂存缓冲区。

sed -e '/hrwang/H' -e '$g' datafile

sed -e '/hrwang/H' -e '$G' datafile

#通过上面两条命令,你会发现g把暂存缓冲区中的内容替换掉了模式空间中当前行的内容,此处即替换了最后一行。而G命令则把暂存缓冲区的内容追加到了模式空间的当前行后。此处即追加到了末尾。

 

 

7. sed脚本

sed脚本就是写在文件中的一列sed命令。脚本中,要求命令的末尾不能有任何多余的空格或文本。如果在一行中有多个命令,要用分号分隔。执行脚本 时,sed先将输入文件中第一行复制到模式缓冲区,然后对其执行脚本中所有的命令。每一行处理完毕后,sed再复制文件中下一行到模式缓冲区,对其执行脚 本中所有命令。使用sed脚本时,不再用引号来确保sed命令不被shell解释。例如sed脚本script:

#handle datafile
3i\
~~~~~~~~~~~~~~~~~~~~~
3,$s/\(hrwang\) is
 \(mjfan\)/\2 is \1/
$a\
We will love eachother forever!!
 

 

 

#sed -f script datafile
My name is hrwang
Your name is mjfan
~~~~~~~~~~~~~~~~~~~~~
mjfan is hrwang's husband.          #啦啦~~~
mjfan is hrwang's wife.
We will love eachother forever!!

 

 

1. Sed简介 

sed 是一种在线编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。以下介绍的是Gnu版本的Sed 3.02。 

2. 定址 

可以通过定址来定位你所希望编辑的行,该地址用数字构成,用逗号分隔的两个行数表示以这两行为起止的行的范围(包括行数表示的那两行)。如1,3表示1,2,3行,美元符号($)表示最后一行。范围可以通过数据,正则表达式或者二者结合的方式确定 。 

 

3. Sed命令 

调用sed命令有两种形式: 

sed [options] 'command' file(s) 

sed [options] -f scriptfile file(s) 

a\ 

在当前行后面加入一行文本。 

b lable 

分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾。 

c\ 

用新的文本改变本行的文本。 

从模板块(Pattern space)位置删除行。 

删除模板块的第一行。 

i\ 

在当前行上面插入文本。 

拷贝模板块的内容到内存中的缓冲区。 

追加模板块的内容到内存中的缓冲区 

获得内存缓冲区的内容,并替代当前模板块中的文本。 

获得内存缓冲区的内容,并追加到当前模板块文本的后面。 

列表不能打印字符的清单。 

读取下一个输入行,用下一个命令处理新的行而不是用第一个命令。 

追加下一个输入行到模板块后面并在二者间嵌入一个新行,改变当前行号码。 

打印模板块的行。 

P(大写) 

打印模板块的第一行。 

退出Sed。 

r file 

从file中读行。 

t label 

if分支,从最后一行开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。 

T label 

错误分支,从最后一行开始,一旦发生错误或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。 

w file 

写并追加模板块到file末尾。 

W file 

写并追加模板块的第一行到file末尾。 

表示后面的命令对所有没有被选定的行发生作用。 

s/re/string 

用string替换正则表达式re。 

打印当前行号码。 

把注释扩展到下一个换行符以前。 

以下的是替换标记 

g表示行内全面替换。 

p表示打印行。 

w表示把行写入一个文件。 

x表示互换模板块中的文本和缓冲区中的文本。 

y表示把一个字符翻译为另外的字符(但是不用于正则表达式) 

 

4. 选项 

-e command, --expression=command 

允许多台编辑。 

-h, --help 

打印帮助,并显示bug列表的地址。 

-n, --quiet, --silent 

 

取消默认输出。 

-f, --filer=script-file 

引导sed脚本文件名。 

-V, --version 

打印版本和版权信息。 

 

5. 元字符集^ 

锚定行的开始 如:/^sed/匹配所有以sed开头的行。  

锚定行的结束 如:/sed$/匹配所有以sed结尾的行。  

匹配一个非换行符的字符 如:/s.d/匹配s后接一个任意字符,然后是d。  

匹配零或多个字符 如:/*sed/匹配所有模板是一个或多个空格后紧跟sed的行。

[]

匹配一个指定范围内的字符,如/[Ss]ed/匹配sed和Sed。

[^]

匹配一个不在指定范围内的字符,如:/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行。

\(..\)

保存匹配的字符,如s/\(love\)able/\1rs,loveable被替换成lovers。

&

保存搜索字符用来替换其他字符,如s/love/**&**/,love这成**love**。  

\< 

锚定单词的开始,如:/\<love/匹配包含以love开头的单词的行。  

\> 

锚定单词的结束,如/love\>/匹配包含以love结尾的单词的行。  

x\{m\} 

重复字符x,m次,如:/0\{5\}/匹配包含5个o的行。  

x\{m,\} 

重复字符x,至少m次,如:/o\{5,\}/匹配至少有5个o的行。  

x\{m,n\} 

重复字符x,至少m次,不多于n次,如:/o\{5,10\}/匹配5--10个o的行。 

6. 实例 

删除:d命令 

$ sed '2d' example-----删除example文件的第二行。 

$ sed '2,$d' example-----删除example文件的第二行到末尾所有行。 

$ sed '$d' example-----删除example文件的最后一行。 

$ sed '/test/'d example-----删除example文件所有包含test的行。 

替换:s命令 

$ sed 's/test/mytest/g' example-----在整行范围内把test替换为mytest。如果没有g标记,则只有每行第一个匹配的test被替换成mytest。 

$ sed -n 's/^test/mytest/p' example-----(-n)选项和p标志一起使用表示只打印那些发生替换的行。也就是说,如果某一行开头的test被替换成mytest,就打印它。 

$ sed 's/^192.168.0.1/&localhost/' example-----&符号表示替换换字符串中被找到的部份。所有以192.168.0.1开头的行都会被替换成它自已加 localhost,变成192.168.0.1localhost。 

$ sed -n 's/\(love\)able/\1rs/p' example-----love被标记为1,所有loveable会被替换成lovers,而且替换的行会被打印出来。 

$ sed 's#10#100#g' example-----不论什么字符,紧跟着s命令的都被认为是新的分隔符,所以,“#”在这里是分隔符,代替了默认的“/”分隔符。表示把所有10替换成100。 

选定行的范围:逗号 

$ sed -n '/test/,/check/p' example-----所有在模板test和check所确定的范围内的行都被打印。 

$ sed -n '5,/^test/p' example-----打印从第五行开始到第一个包含以test开始的行之间的所有行。 

$ sed '/test/,/check/s/$/sed test/' example-----对于模板test和west之间的行,每行的末尾用字符串sed test替换。 

多点编辑:e命令 

$ sed -e '1,5d' -e 's/test/check/' example-----(-e)选项允许在同一行里执行多条命令。如例子所示,第一条命令删除1至5行,第二条命令用check替换test。命令的执 行顺序对结果有影响。如果两个命令都是替换命令,那么第一个替换命令将影响第二个替换命令的结果。 

$ sed --expression='s/test/check/' --expression='/love/d' example-----一个比-e更好的命令是--expression。它能给sed表达式赋值。 

从文件读入:r命令 

$ sed '/test/r file' example-----file里的内容被读进来,显示在与test匹配的行后面,如果匹配多行,则file的内容将显示在所有匹配行的下面。 

写入文件:w命令 

$ sed -n '/test/w file' example-----在example中所有包含test的行都被写入file里。 

追加命令:a命令 

$ sed '/^test/a\\--->this is a example' example<-----'this is a example'被追加到以test开头的行后面,sed要求命令a后面有一个反斜杠。 

插入:i命令 

$ sed '/test/i\\ 

new line 

-------------------------' example 

如果test被匹配,则把反斜杠后面的文本插入到匹配行的前面。 

下一个:n命令 

$ sed '/test/{ n; s/aa/bb/; }' example-----如果test被匹配,则移动到匹配行的下一行,替换这一行的aa,变为bb,并打印该行,然后继续。 

变形:y命令 

$ sed '1,10y/abcde/ABCDE/' example-----把1--10行内所有abcde转变为大写,注意,正则表达式元字符不能使用这个命令。 

退出:q命令 

$ sed '10q' example-----打印完第10行后,退出sed。 

保持和获取:h命令和G命令 

$ sed -e '/test/h' -e '$G example-----在sed处理文件的时候,每一行都被保存在一个叫模式空间的临时缓冲区中,除非行被删除或者输出被取消,否则所有被处理的行都将 打印在屏幕上。接着模式空间被清空,并存入新的一行等待处理。在这个例子里,匹配test的行被找到后,将存入模式空间,h命令将其复制并存入一个称为保 持缓存区的特殊缓冲区内。第二条语句的意思是,当到达最后一行后,G命令取出保持缓冲区的行,然后把它放回模式空间中,且追加到现在已经存在于模式空间中 的行的末尾。在这个例子中就是追加到最后一行。简单来说,任何包含test的行都被复制并追加到该文件的末尾。 

保持和互换:h命令和x命令 

$ sed -e '/test/h' -e '/check/x' example -----互换模式空间和保持缓冲区的内容。也就是把包含test与check的行互换。 

7. 脚本 

Sed脚本是一个sed的命令清单,启动Sed时以-f选项引导脚本文件名。Sed对于脚本中输入的命令非常挑剔,在命令的末尾不能有任何空白或文本,如果在一行中有多个命令,要用分号分隔。以#开头的行为注释行,且不能跨行。

 

 

sed 高级用法

首先,应该明白模式空间的定义。模式空间就是读入行所在的缓存,sed对文本行进行的处理都是在这个缓存中进行的。这对接下来的学习是有帮助的。
在正常情况下,sed将待处理的行读入模式空间,脚本中的命令就一条接着一条的对该行进行处理,直到脚本执行完毕,然后该行被输出,模式空间请空;然后重复刚才的动作,文件中的新的一行被读入,直到文件处理完备。
但是,各种各样的原因,比如用户希望在某个条件下脚本中的某个命令被执行,或者希望模式空间得到保留以便下一次的处理,都有可能使得sed在处理文件的时候不按照正常的流程来进行。这个时候,sed设置了一些高级命令来满足用户的要求。
总的来说,这些命令可以划分为以下三类:
1. N、D、P:处理多行模式空间的问题;
2. H、h、G、g、x:将模式空间的内容放入存储空间以便接下来的编辑;
3. :、b、t:在脚本中实现分支与条件结构。
多行模式空间的处理:
由于正则表达式是面向行的,因此,如若某个词组一不分位于某行的结尾,另外一部分又在下一行的开始,这个时候用grep等命令来处理就相当的困难。然而,借助于sed的多行命令N、D、P,却可以轻易地完成这个任务。
多行Next(N)命令是相对于next(n)命令的,后者将模式空间中的内容输出,然后把下一行读入模式空间,但是脚本并不会转移到开始而是从当前的n 命令之后开始执行;而前者则保存原来模式空间中的内容,再把新的一行读入,两者之间依靠一个换行符"\n"来分隔。在N命令执行后,控制流将继续用N命令 以后的命令对模式空间进行处理。
值得注意的是,在多行模式中,特殊字符"^"和"$"匹配的是模式空间的最开始与最末尾,而不是内嵌"\n"的开始与末尾。
例1:
$ cat expl.1
Consult Section 3.1 in the Owner and Operator
Guide for a description of the tape drives
available on your system.
现在要将"Owner and Operator Guide"替换为"Installation Guide":
$ sed '/Operator$/{
> N
> s/Owner and Operator\nGuide/Installation Guide\
> /
> }' expl.1
在上面的例子中要注意的是,行与行之间存在内嵌的换行符;另外在用于替代的内容中要插入换行符的话,要用如上的"\"的转义。
再看一个例子:
例2:
$ cat expl.2
Consult Section 3.1 in the Owner and Operator
Guide for a description of the tape drives
available on your system.

Look in the Owner and Operator Guide shipped with your system.

Two manuals are provided including the Owner and
Operator Guide and the User Guide.

The Owner and Operator Guide is shipped with your system.
$ sed 's/Owner and Operator Guide/Installation Guide/
> /Owner/{
> N
> s/ *\n/ /
> s/Owner and Operator Guide */Installation Guide\
> /
}' expl.2
结果得到:
Consult Section 3.1 in the Installation Guide
for a description of the tape drives
available on your system.

Look in the Installation Guide shipped with your system.

Two manuals are provided including the Installation Guide
and the User Guide.

The Installation Guide is shipped with your system.
看上去sed命令中作了两次替换是多余的。实际上,如果去掉第一次替换,再运行脚本,就会发现输出存在两个问题。一个是结果中最后一行不会被替换(在某些 版本的sed中甚至不会被输出)。这是因为最后一行匹配了"Owner",执行N命令,但是已经到了文件末尾,某些版本就会直接打印这行再退出,而另外一 些版本则是不作出打印立即退出。对于这个问题可以通过命令"$!N"来解决。这表示N命令对最后一行不起作用。另外一个问题是"look manuals"一段被拆为两行,而且与下一段的空行被删除了。这是因为内嵌的换行符被替换的结果。因此,sed中做两次替换一点也不是多余的。
例3:
$ cat expl.3
<para>

This is a test paragraph in Interleaf style ASCII. Another line
in a paragraph. Yet another.

<Figure Begin>

v.1111111111111111111111100000000000000000001111111111111000000
100001000100100010001000001000000000000000000000000000000000000
000000

<Figure End>

<para>

More lines of text to be found after the figure.
These lines should print.
我们的sed命令是这样的:
$ sed '/<para>{
> N
> c\
> .LP
> }
> /<Figure Begin>/,/<Figure End>/{
> w fig.interleaf
> /<Figure End>/i\
> .FG\
> <insert figure here>\
> .FE
> d
> }
> /^$/d' expl.3
运行后得到的结果是:
.LP
This is a test paragraph in Interleaf style ASCII. Another line
in a paragraph. Yet another.
.FG
<insert figure here>
.FE
.LP
More lines of text to e found after the figure.
These lines should print.
而<Figure Begin>与<Figure End>之间的内容则写入文件"fig.interleaf"。值得注意的是命令"d"并不会影响命令i插入的内容。
命令"d"作用是删除模式空间的内容,然后读入新的行,sed脚本从头再次开始执行。而命令"D"的不同之处在于它删除的是直到第一个内嵌换行符为止的模式空间的一部分,但是不会读入新的行,脚本将回到开始对剩下内容进行处理。
例4:
$ cat expl.4
This line is followed by 1 blank line.

This line is followed by 2 blank line.


This line is followed by 3 blank line.



This line is followed by 4 blank line.




This is the end.
不同的删除命令获得不同的结果:
$ sed '/^$/{ $ sed '/^$/{
> N > N
> /^\n$/d > /^\n$/D
> }' expl.4 > }' expl.4
sed对文件中每一行(不管处理与否)的默认动作是将其输出,如果加上选项"-n",则输出动作会被抑制,这时还希望输出就需要打印命令。单行模式空间的打印命令是"p",多行模式空间的打印命令是"P"。P命令打印的是模式空间中直到第一个内嵌换行符为止的一部分。
P命令通常出现在N命令之后D命令之前,由此构成一个输入输出循环。在这种情况下,模式空间中始终存在两行文本,而输出始终是一行文本。使用这种循环的目 的在于输出模式空间中的第一行,然后脚本回到起始处,再对空间中的第二行进行处理。设想一下,如果没有这个循环,当脚本执行完备,模式空间中的内容都会被 输出,可能就不符合使用者的要求或者降低了程序执行的效率。
下面是一个例子:
例5:
$ cat expl.5
Here are examples of the UNIX
System. Where UNIX
System appears, it should be the UNIX
Operating System.
$ sed '/UNIX$/{
> N
> /\nSystem/{
> s// Operating &/
> P
> D
> }
> }' expl.5
替换的结果是:
Here are examples of the UNIX Operating
System. Where UNIX Operating
System appears, it should be the UNIX
Operating System.
可以将sed命令中的"P"、"D"换作小写,比较一下两种类型的命令的不同之处。
下面的例子就有相当的难度了:
例6:
$ cat expl.6
I want to see @fl(what will happen) if we put the
font change commands @fl(on a set of lines). If I understand
things (correctly), the @fl(third) line causes problems. (No?).
Is this really the case, or is it (maybe) just something else?

Let's test having two on a line @fl(here) and @fl(there) as
well as one that begins on one line and ends @fl(somewhere
on another line). What if @fl(it is here) on the line?
Another @fl(one).
现在要作的就是将"fl@(…)替换为"\fB(…)\fR。以下就是满足条件的sed命令:
$ sed 's/@fl(\([^)]*\))/\\fB\1\\fR/g
> /@fl(.*/{
> N
> s/@fl(\(.*\n[^)]*\))/\\fB\1\\fR/g
> P
> D
> }' expl.6
然而,如果不使用这种输入输出循环,而是单单用N来实现的话,就会出现问题:
$ sed 's/@fl(\([^)]*\))/\\fB\1\\fR/g
> /@fl(.*/{
> N
> s/@fl(\(.*\n[^)]*\))/\\fB\1\\fR/g
> }' expl.6
这样的sed脚本是有漏洞的。


对行进行存储:
前面已经解释了模式空间的定义,而在sed中还有一个缓存叫作存储空间。在模式空间和存储空间中的内容可以通过一组命令互相拷贝:
命令 简写 功能
Hold h或H 将模式空间的内容拷贝或附加到存储空间
Get g或G 将存储空间的内容拷贝或附加到模式空间
Exchange x 交换模式空间和存储空间中的内容
命令的大小写的区别在于大写的命令是将源空间的内容附加到目标空间,而小写的命令则是用源空间的内容覆盖目标空间。值得注意的是,不管是Hold命令还是Get命令,都会在目的空间的原有内容之后加上一个换行符,然后才把源空间中的内容加到换行符的后面。
从下面这个例子,可以体会这部分内容的初步应用:
例7:
$ cat expl.7
1
2
11
22
111
222
我们要做的工作就是将第一行与第二行,第三行与第四行,第五行与第六行互换。sed的命令各式是:
$ sed '
> /1/{
> h
> d
> }
> /2/{
> G
> }' expl.7
这个过程是这样的:首先,sed将第一行读入模式空间,然后h命令将其放入存储空间保存起来,一个d命令又把模式空间中的内容清空;接着sed把第二行读入模式空间,然后G命令把存储空间中的内容附加到模式空间(注意的是在模式空间的原内容末尾是加了一个换行符的)。
最后得到的结果如下:
2
1
22
11
222
111
使用H或h命令的时候,比较常见的是在这个命令之后加上d命令,这样一来,sed脚本不会到达最后,因而模式空间中的内容也就不会输出了。另外,如果把d换作n,或者把G换作g,都不会达到目的的。
子母的大小写转换什么最方便,估计是tr了。
$ tr "[a-z]" "[A-Z]" File
很利害的是sed也可以完成这个转换。相应的命令是y:
$ sed '
> /[address]/y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' File
然而y命令是对整个行完全进行修改,因此如果只是将行里面的几个字符变换大小写的话,这样做是行不通的。为完成这个工作,需要借助上面刚提到的Hold和Get命令了。
cat expl.8
find the Match statement
Consult the Get statement
using the Read statement to retrieve data
$ sed '/the .* statement/{
> h
> s/.*the \(.*\) statement.*/\1/
> y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
> G
> s/\(.*\)\n\(.*the \).*\( statement.*\)/\2\1\3/
> }' expl.8
以第一行的处理过程来说明这段命令的含意:
(1) "find the Match statement"被放入存储空间;
(2) 替换改行得到:Match;
(3) 将(2)的结果转换为大写:MATCH;
(4) 从存储空间去处(1)保留的内容附加到模式空间,此时模式空间的内容为:
MATCH\nfind the Match statement
(5) 再次对模式空间的内容替换得到:find the MATCH statement。
下面将举到的例子要用到比较扎实的正则表达式,不过没有关系,慢慢来,一切问题都是可以解决的。另外这个例子用到的文本主要是和编辑排版有关的,这方面我不大会,所以我就只是把sed脚本拿出来,抓住核心,省掉那些细枝末节的东西:
例9:
$ cat expl.9.sed
h
s/[][\\*.]/\\&/g
x
s/[\\&]/\\&/g
s/^\.XX //
s/$/\//
x
s/^\\\.XX \(.*\)$/\/^\\.XX \/s\/\1//
G
s/\n//
(1) h:讲文本行放入存储空间。
(2) s/[][\\*.]/\\&/g:这个表达式难度比较大,如果在类表达,也就是"[]"中的第一个字符是"]"的话,那么"]"就丧失了它的特 殊含意;另外,唉"[]"中,仅仅只有"\"是有特殊含意的,言下之意就是"*"、"."都是理解为字面意思,要使他们具有特殊意义就必须使用"\"的转 义了;虽然在表达式中没有出现,也要提一下,在"[]"中只有"^"出现在第一的位置时,表示"非"的含意,其余情况就是字面解释,而"$"仅仅是在正则 表达式的末尾时才有特殊含意。"\\"去掉了"\"的特殊含意,"&"表示向前引用,因此,第二个命令的意思就是:将模式空间中的"["、"] "、"\"、"*"、"."依次用"\["、"\]"、"\\"、"\*"、"\."来替换。
(3) x:交换模式空间和存储空间。执行这个命令后模式空间的内容是原文的内容,而存储空间中的内容发生变化,各个特殊字符都被替换成为了"\&"。
(4) s/[\\&]/\\&/g:对模式空间处理,出现的"\"或者"&"都会替换为"\\"或者"\&"。
(5) s/$/\//:这个好理解,就是在模式空间的结尾加上一个"/"。
(6) x:再次交换两个空间的内容。
(7) s/^\\\.XX \(.*\)$/\/^\\.XX \/s\/\1//:这个没有什么难度,就是那几个引用容易把人看晕了,仔细一点,不会有问题的,就略过吧。
(Cool G:略了。
(9) s/\n//:删除换行符。
这个脚本有什么用呢?用以下的文本实验就清楚了:
.XX "asterisk (*) metacharacter"
下面是每次命令的结果,第一行和第二行分别表示模式空间和存储空间的内容:
1. .XX "asterisk (*) metacharacter"
.XX "asterisk (*) metacharacter"

2. \.XX "asterisk (\*) metacharacter"
.XX "asterisk (*) metacharacter"

3. .XX "asterisk (*) metacharacter"
\.XX "asterisk (\*) metacharacter"

4. .XX "asterisk (*) metacharacter"
\.XX "asterisk (\*) metacharacter"

5. "asterisk (*) metacharacter"
\.XX "asterisk (\*) metacharacter"

6. "asterisk (*) metacharacter"/
\.XX "asterisk (\*) metacharacter"

7. \.XX "asterisk (\*) metacharacter"
"asterisk (*) metacharacter"/

8. /^\.XX /s/"asterisk (\*) metacharacter"/
"asterisk (*) metacharacter"/

9. /^\.XX /s/"asterisk (\*) metacharacter"/\n/"asterisk (*) metacharacter"/

10./^\.XX /s/"asterisk (\*) metacharacter"/"asterisk (*) metacharacter"/

看到没有,其实"s/[\\&]/\\&/"没有在我们的例子中没有起作用,但是它不可少,因为在s命令的第二部分,"\"和"&"都是有特殊含意的,所以要预先转义掉其特殊含意。
明白了吗?当你希望用一个shell脚本自动生成一个主要是替换命令的sed脚本的时候,会发现这个以上的内容对特殊字符的处理是多么得关键。
出了上面的应用,存储空间甚至还能够将很多行的内容存储起来供以后的输出。实际上,这一功能对html等具有非常明显的结构的文本非常有效。下面是相关的例子:
例10
cat expl.10
<p>My wife won't let me buy a power saw. She is afraid of an
accident if I use one.
So I rely on a hand saw for a variety of weekend projects like
building shelves.
However, if I made my living as a carpenter, I would
have to use a power
saw. The speed and efficiency provided by power tools
would be essential to being productive.</p>

<p>For people who create and modify text files,
sed and awk are power tools for editing.</p>

<p>Most of the things that you can do with these programs
can be done interactively with a text editor. However,
using these programs can save many hours of repetitive
work in achieving the same result.</p>

$ sed '/^$/!{
> H
> d
> }
> /^$/{
> x
> s/^\n/<p>/
> s/$/<\/p>/
> G
> }' expl.10
运行一下这个命令,看看结果是怎样的。其实结果已经不重要了。通过这个子,应该学会的是脚本中体现的流程控制的思想。脚本的第一部分使用"!"表示对不匹 配的行进行处理,但是这种处理因为"d"的存在,不会走脚本的底部,自然也就不会有任何的输出;在脚本的第二部分中,脚本的确是到了最后的,相应的也清除 了模式空间和存储空间的内容,为读入下一段做好了准备。
本来这个例子已经完了,但是还有种情况,如果文件的最后一行不是空行会出现什么结果?显然,文本的最后一段不会被输出。这种情况怎么处理呢?最明智的办法就是自己"制造"一个空行。新的脚本是这样的:
$ sed '${
> /^$/!{
> H
> s/.*//
> }
> }
> /^$/!{
> H
> d
> }
> /^$/{
> x
> s/^\n/<p>/
> s/$/<\/p>/
> G
> }' expl.10


流程控制命令
为了使使用者在书写sed脚本的时候真正的"自由",sed还允许在脚本中用":"设置记号,然后用"b"和"t"命令进行流程控制。顾名思义,"b"表示"branch","t"表示"test";前者就是分支命令,后者则是测试命令。
首先来看标签的各式是什么。这个标签放置在你希望流程所开始的地方,单独放一行,以冒号开始。冒号与变迁之间不允许有空格或者制表符,标签最后如果有空格的话,也会被认为是标签的一部分。
再来说b命令。它的格式是这样的:
[address]b[label]
它的含意是,如果满足address,则sed流程跟随标签跳转:如果标签指明的话,脚本首先假设这个标签在b命令以下的某行,然后转入该行执行相应的命令;如果这个标签不存在的话,控制流程就直接跳到脚本的末尾。否则继续执行后续的命令。
在某些情况下,b命令和!命令有些相似,但是!命令只能对紧挨它的{}中的内容起作用,而b命令则给予使用者足够的自由在sed脚本中选择哪些命令应该被执行,哪些命令不应该被执行。下面提供几种b命令的经典用法:
(1) 创建循环:
:top
command1
command2
/pattern/b top
command3
(2) 忽略某些不满足条件的命令:
command1
/patern/b end
command2
:end
command3
(3) 命令的两个部分只能执行其中一个:
command1
/pattern/b dothere
command
b
:dothere
command3
t命令的格式和b命令是一样的:
[address]t[label]
它表示的是如果满足address的话,sed脚本就会根据t命令指示的标签进行流程转移。而标签的规则和上面讲的b命令的规则是一样的。下面也给出一个例子:
s/pattern/replacement/
t break
command
:break
还是用例6的sed脚本为例子。其实仔细思考一下就会发现这个脚本不是足够强大:如果某个@fl结构跨越了两行,比如说三行怎么办?这就需要下面这个加强版的sed了:
$ cat expl.6.sed
:begin
/@fl(\([^)]*\))/{
s//\\fB\1\\fR/g
b begin
}
/@fl(.*/{
N
s/@f1(\([^)]*\n[^)]*\))/\\fB\1\\fR/g
t again
b begin
}
:again
P
D

 

 

 

  1. 1. Sed简介  
  2. sed 是 一种在线编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处 理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输 出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。以下介绍的是Gnu版本的Sed 3.02。  
  3. 2. 定址  
  4. 可以通过定址来定位你所希望编辑的行,该地址用数字构成,用逗号分隔的两个行数表示以这两行为起止的行的范围(包括行数表示的那两行)。如1,3表示1,2,3行,美元符号($)表示最后一行。范围可以通过数据,正则表达式或者二者结合的方式确定 。  
  5.   
  6. 3. Sed命令  
  7. 调用sed命令有两种形式:  
  8. *  
  9. sed [options] 'command' file(s)  
  10. *  
  11. sed [options] -f scriptfile file(s)  
  12. a\  
  13. 在当前行后面加入一行文本。  
  14. b lable  
  15. 分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾。  
  16. c\  
  17. 用新的文本改变本行的文本。  
  18. d  
  19. 从模板块(Pattern space)位置删除行。  
  20. D  
  21. 删除模板块的第一行。  
  22. i\  
  23. 在当前行上面插入文本。  
  24. h  
  25. 拷贝模板块的内容到内存中的缓冲区。  
  26. H  
  27. 追加模板块的内容到内存中的缓冲区  
  28. g  
  29. 获得内存缓冲区的内容,并替代当前模板块中的文本。  
  30. G  
  31. 获得内存缓冲区的内容,并追加到当前模板块文本的后面。  
  32. l  
  33. 列表不能打印字符的清单。  
  34. n  
  35. 读取下一个输入行,用下一个命令处理新的行而不是用第一个命令。  
  36. N  
  37. 追加下一个输入行到模板块后面并在二者间嵌入一个新行,改变当前行号码。  
  38. p  
  39. 打印模板块的行。  
  40. P(大写)  
  41. 打印模板块的第一行。  
  42. q  
  43. 退出Sed。  
  44. r file  
  45. 从file中读行。  
  46. t label  
  47. if分支,从最后一行开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。  
  48. T label  
  49. 错误分支,从最后一行开始,一旦发生错误或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。  
  50. w file  
  51. 写并追加模板块到file末尾。  
  52. W file  
  53. 写并追加模板块的第一行到file末尾。  
  54. !  
  55. 表示后面的命令对所有没有被选定的行发生作用。  
  56. s/re/string  
  57. 用string替换正则表达式re。  
  58. =  
  59. 打印当前行号码。  
  60. #  
  61. 把注释扩展到下一个换行符以前。  
  62. 以下的是替换标记  
  63. *  
  64. g表示行内全面替换。  
  65. *  
  66. p表示打印行。  
  67. *  
  68. w表示把行写入一个文件。  
  69. *  
  70. x表示互换模板块中的文本和缓冲区中的文本。  
  71. *  
  72. y表示把一个字符翻译为另外的字符(但是不用于正则表达式)  
  73.   
  74. 4. 选项  
  75. -e command, --expression=command  
  76. 允许多台编辑。  
  77. -h, --help  
  78. 打印帮助,并显示bug列表的地址。  
  79. -n, --quiet, --silent  
  80.   
  81. 取消默认输出。  
  82. -f, --filer=script-file  
  83. 引导sed脚本文件名。  
  84. -V, --version  
  85. 打印版本和版权信息。  
  86.   
  87. 5. 元字符集^  
  88. 锚定行的开始 如:/^sed/匹配所有以sed开头的行。   
  89. $  
  90. 锚定行的结束 如:/sed$/匹配所有以sed结尾的行。   
  91. .  
  92. 匹配一个非换行符的字符 如:/s.d/匹配s后接一个任意字符,然后是d。   
  93. *  
  94. 匹配零或多个字符 如:/*sed/匹配所有模板是一个或多个空格后紧跟sed的行。  
  95. [] 
  96. 匹配一个指定范围内的字符,如/[Ss]ed/匹配sed和Sed。  
  97. [^] 
  98. 匹配一个不在指定范围内的字符,如:/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行。  
  99. \(..\) 
  100. 保存匹配的字符,如s/\(love\)able/\1rs,loveable被替换成lovers。  
  101. 保存搜索字符用来替换其他字符,如s/love/**&**/,love这成**love**。   
  102. \<  
  103. 锚定单词的开始,如:/\<love/匹配包含以love开头的单词的行。   
  104. \>  
  105. 锚定单词的结束,如/love\>/匹配包含以love结尾的单词的行。   
  106. x\{m\}  
  107. 重复字符x,m次,如:/0\{5\}/匹配包含5个o的行。   
  108. x\{m,\}  
  109. 重复字符x,至少m次,如:/o\{5,\}/匹配至少有5个o的行。   
  110. x\{m,n\}  
  111. 重复字符x,至少m次,不多于n次,如:/o\{5,10\}/匹配5--10个o的行。  
  112. 6. 实例  
  113. 删除:d命令  
  114. *  
  115. $ sed '2d' example-----删除example文件的第二行。  
  116. *  
  117. $ sed '2,$d' example-----删除example文件的第二行到末尾所有行。  
  118. *  
  119. $ sed '$d' example-----删除example文件的最后一行。  
  120. *  
  121. $ sed '/test/'d example-----删除example文件所有包含test的行。  
  122. 替换:s命令  
  123. *  
  124. $ sed 's/test/mytest/g' example-----在整行范围内把test替换为mytest。如果没有g标记,则只有每行第一个匹配的test被替换成mytest。  
  125. *  
  126. $ sed -n 's/^test/mytest/p' example-----(-n)选项和p标志一起使用表示只打印那些发生替换的行。也就是说,如果某一行开头的test被替换成mytest,就打印它。  
  127. *  
  128. $ sed 's/^192.168.0.1/&localhost/' example-----&符号表示替换换字符串中被找到的部份。所有以192.168.0.1开头的行都会被替换成它自已加 localhost,变成192.168.0.1localhost。  
  129. *  
  130. $ sed -n 's/\(love\)able/\1rs/p' example-----love被标记为1,所有loveable会被替换成lovers,而且替换的行会被打印出来。  
  131. *  
  132. $ sed 's#10#100#g' example-----不论什么字符,紧跟着s命令的都被认为是新的分隔符,所以,“#”在这里是分隔符,代替了默认的“/”分隔符。表示把所有10替换成100。  
  133. 选定行的范围:逗号  
  134. *  
  135. $ sed -n '/test/,/check/p' example-----所有在模板test和check所确定的范围内的行都被打印。  
  136. *  
  137. $ sed -n '5,/^test/p' example-----打印从第五行开始到第一个包含以test开始的行之间的所有行。  
  138. *  
  139. $ sed '/test/,/check/s/$/sed test/' example-----对于模板test和west之间的行,每行的末尾用字符串sed test替换。  
  140. 多点编辑:e命令  
  141. *  
  142. $ sed -e '1,5d' -e 's/test/check/' example-----(-e)选项允许在同一行里执行多条命令。如例子所示,第一条命令删除1至5行,第二条命令用check替换test。命令的执 行顺序对结果有影响。如果两个命令都是替换命令,那么第一个替换命令将影响第二个替换命令的结果。  
  143. *  
  144. $ sed --expression='s/test/check/' --expression='/love/d' example-----一个比-e更好的命令是--expression。它能给sed表达式赋值。  
  145. 从文件读入:r命令  
  146. *  
  147. $ sed '/test/r file' example-----file里的内容被读进来,显示在与test匹配的行后面,如果匹配多行,则file的内容将显示在所有匹配行的下面。  
  148. 写入文件:w命令  
  149. *  
  150. $ sed -n '/test/w file' example-----在example中所有包含test的行都被写入file里。  
  151. 追加命令:a命令  
  152. *  
  153. $ sed '/^test/a\\--->this is a example' example<-----'this is a example'被追加到以test开头的行后面,sed要求命令a后面有一个反斜杠。  
  154. 插入:i命令  
  155. $ sed '/test/i\\  
  156. new line  
  157. -------------------------' example  
  158. 如果test被匹配,则把反斜杠后面的文本插入到匹配行的前面。  
  159. 下一个:n命令  
  160. *  
  161. $ sed '/test/{ n; s/aa/bb/; }' example-----如果test被匹配,则移动到匹配行的下一行,替换这一行的aa,变为bb,并打印该行,然后继续。  
  162. 变形:y命令  
  163. *  
  164. $ sed '1,10y/abcde/ABCDE/' example-----把1--10行内所有abcde转变为大写,注意,正则表达式元字符不能使用这个命令。  
  165. 退出:q命令  
  166. *  
  167. $ sed '10q' example-----打印完第10行后,退出sed。  
  168. 保持和获取:h命令和G命令  
  169. *  
  170. $ sed -e '/test/h' -e '$G example----- 在sed处理文件的时候,每一行都被保存在一个叫模式空间的临时缓冲区中,除非行被删除或者输出被取消,否则所有被处理的行都将 打印在屏幕上。接着模式 空间被清空,并存入新的一行等待处理。在这个例子里,匹配test的行被找到后,将存入模式空间,h命令将其复制并存入一个称为保 持缓存区的特殊缓冲区 内。第二条语句的意思是,当到达最后一行后,G命令取出保持缓冲区的行,然后把它放回模式空间中,且追加到现在已经存在于模式空间中 的行的末尾。在这个 例子中就是追加到最后一行。简单来说,任何包含test的行都被复制并追加到该文件的末尾。  
  171. 保持和互换:h命令和x命令  
  172. *  
  173. $ sed -e '/test/h' -e '/check/x' example -----互换模式空间和保持缓冲区的内容。也就是把包含test与check的行互换。  
  174. 7. 脚本  
  175. Sed脚本是一个sed的命令清单,启动Sed时以-f选项引导脚本文件名。Sed对于脚本中输入的命令非常挑剔,在命令的末尾不能有任何空白或文本,如果在一行中有多个命令,要用分号分隔。以#开头的行为注释行,且不能跨行。

 

 

 

HANDY ONE-LINERS FOR SED (Unix stream editor)               Mar. 23, 2001
compiled by Eric Pement <pemente@northpark.edu>               version 5.1
Latest version of this file is usually at:
   http://www.student.northpark.edu/pemente/sed/sed1line.txt
   http://www.cornerstonemag.com/sed/sed1line.txt
This file is also available in Portuguese at:
   http://www.lrv.ufsc.br/wmaker/sed_ptBR.html

FILE SPACING:

 # double space a file
 sed G

 # double space a file which already has blank lines in it. Output file
 # should contain no more than one blank line between lines of text.
 sed '/^$/d;G'

 # triple space a file
 sed 'G;G'

 # undo double-spacing (assumes even-numbered lines are always blank)
 sed 'n;d'

NUMBERING:

 # number each line of a file (simple left alignment). Using a tab (see
 # note on '\t' at end of file) instead of space will preserve margins.
 sed = filename | sed 'N;s/\n/\t/'

 # number each line of a file (number on left, right-aligned)
 sed = filename | sed 'N; s/^/     /; s/ *\(.\{6,\}\)\n/\1  /'

 # number each line of file, but only print numbers if line is not blank
 sed '/./=' filename | sed '/./N; s/\n/ /'

 # count lines (emulates "wc -l")
 sed -n '$='

TEXT CONVERSION AND SUBSTITUTION:

 # IN UNIX ENVIRONMENT: convert DOS newlines (CR/LF) to Unix format
 sed 's/.$//'               # assumes that all lines end with CR/LF
 sed 's/^M$//'              # in bash/tcsh, press Ctrl-V then Ctrl-M
 sed 's/\x0D$//'            # gsed 3.02.80, but top script is easier

 # IN UNIX ENVIRONMENT: convert Unix newlines (LF) to DOS format
 sed "s/$/`echo -e \\\r`/"            # command line under ksh
 sed 's/$'"/`echo \\\r`/"             # command line under bash
 sed "s/$/`echo \\\r`/"               # command line under zsh
 sed 's/$/\r/'                        # gsed 3.02.80

 # IN DOS ENVIRONMENT: convert Unix newlines (LF) to DOS format
 sed "s/$//"                          # method 1
 sed -n p                             # method 2

 # IN DOS ENVIRONMENT: convert DOS newlines (CR/LF) to Unix format
 # Cannot be done with DOS versions of sed. Use "tr" instead.
 tr -d \r <infile >outfile            # GNU tr version 1.22 or higher

 # delete leading whitespace (spaces, tabs) from front of each line
 # aligns all text flush left
 sed 's/^[ \t]*//'                    # see note on '\t' at end of file

 # delete trailing whitespace (spaces, tabs) from end of each line
 sed 's/[ \t]*$//'                    # see note on '\t' at end of file

 # delete BOTH leading and trailing whitespace from each line
 sed 's/^[ \t]*//;s/[ \t]*$//'

 # insert 5 blank spaces at beginning of each line (make page offset)
 sed 's/^/     /'

 # align all text flush right on a 79-column width
 sed -e :a -e 's/^.\{1,78\}$/ &/;ta'  # set at 78 plus 1 space

 # center all text in the middle of 79-column width. In method 1,
 # spaces at the beginning of the line are significant, and trailing
 # spaces are appended at the end of the line. In method 2, spaces at
 # the beginning of the line are discarded in centering the line, and
 # no trailing spaces appear at the end of lines.
 sed  -e :a -e 's/^.\{1,77\}$/ & /;ta'                     # method 1
 sed  -e :a -e 's/^.\{1,77\}$/ &/;ta' -e 's/\( *\)\1/\1/'  # method 2

 # substitute (find and replace) "foo" with "bar" on each line
 sed 's/foo/bar/'             # replaces only 1st instance in a line
 sed 's/foo/bar/4'            # replaces only 4th instance in a line
 sed 's/foo/bar/g'            # replaces ALL instances in a line
 sed 's/\(.*\)foo\(.*foo\)/\1bar\2/' # replace the next-to-last case
 sed 's/\(.*\)foo/\1bar/'            # replace only the last case

 # substitute "foo" with "bar" ONLY for lines which contain "baz"
 sed '/baz/s/foo/bar/g'

 # substitute "foo" with "bar" EXCEPT for lines which contain "baz"
 sed '/baz/!s/foo/bar/g'

 # change "scarlet" or "ruby" or "puce" to "red"
 sed 's/scarlet/red/g;s/ruby/red/g;s/puce/red/g'   # most seds
 gsed 's/scarlet\|ruby\|puce/red/g'                # GNU sed only

 # reverse order of lines (emulates "tac")
 # bug/feature in HHsed v1.5 causes blank lines to be deleted
 sed '1!G;h;$!d'               # method 1
 sed -n '1!G;h;$p'             # method 2

 # reverse each character on the line (emulates "rev")
 sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//'

 # join pairs of lines side-by-side (like "paste")
 sed '$!N;s/\n/ /'

 # if a line ends with a backslash, append the next line to it
 sed -e :a -e '/\\$/N; s/\\\n//; ta'

 # if a line begins with an equal sign, append it to the previous line
 # and replace the "=" with a single space
 sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D'

 # add commas to numeric strings, changing "1234567" to "1,234,567"
 gsed ':a;s/\B[0-9]\{3\}\>/,&/;ta'                     # GNU sed
 sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta'  # other seds

 # add commas to numbers with decimal points and minus signs (GNU sed)
 gsed ':a;s/\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)/\1\2,\3/g;ta'

 # add a blank line every 5 lines (after lines 5, 10, 15, 20, etc.)
 gsed '0~5G'                  # GNU sed only
 sed 'n;n;n;n;G;'             # other seds

SELECTIVE PRINTING OF CERTAIN LINES:

 # print first 10 lines of file (emulates behavior of "head")
 sed 10q

 # print first line of file (emulates "head -1")
 sed q

 # print the last 10 lines of a file (emulates "tail")
 sed -e :a -e '$q;N;11,$D;ba'

 # print the last 2 lines of a file (emulates "tail -2")
 sed '$!N;$!D'

 # print the last line of a file (emulates "tail -1")
 sed '$!d'                    # method 1
 sed -n '$p'                  # method 2

 # print only lines which match regular expression (emulates "grep")
 sed -n '/regexp/p'           # method 1
 sed '/regexp/!d'             # method 2

 # print only lines which do NOT match regexp (emulates "grep -v")
 sed -n '/regexp/!p'          # method 1, corresponds to above
 sed '/regexp/d'              # method 2, simpler syntax

 # print the line immediately before a regexp, but not the line
 # containing the regexp
 sed -n '/regexp/{g;1!p;};h'

 # print the line immediately after a regexp, but not the line
 # containing the regexp
 sed -n '/regexp/{n;p;}'

 # print 1 line of context before and after regexp, with line number
 # indicating where the regexp occurred (similar to "grep -A1 -B1")
 sed -n -e '/regexp/{=;x;1!p;g;$!N;p;D;}' -e h

 # grep for AAA and BBB and CCC (in any order)
 sed '/AAA/!d; /BBB/!d; /CCC/!d'

 # grep for AAA and BBB and CCC (in that order)
 sed '/AAA.*BBB.*CCC/!d'

 # grep for AAA or BBB or CCC (emulates "egrep")
 sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d    # most seds
 gsed '/AAA\|BBB\|CCC/!d'                        # GNU sed only

 # print paragraph if it contains AAA (blank lines separate paragraphs)
 # HHsed v1.5 must insert a 'G;' after 'x;' in the next 3 scripts below
 sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;'

 # print paragraph if it contains AAA and BBB and CCC (in any order)
 sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;/BBB/!d;/CCC/!d'

 # print paragraph if it contains AAA or BBB or CCC
 sed -e '/./{H;$!d;}' -e 'x;/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d
 gsed '/./{H;$!d;};x;/AAA\|BBB\|CCC/b;d'         # GNU sed only

 # print only lines of 65 characters or longer
 sed -n '/^.\{65\}/p'

 # print only lines of less than 65 characters
 sed -n '/^.\{65\}/!p'        # method 1, corresponds to above
 sed '/^.\{65\}/d'            # method 2, simpler syntax

 # print section of file from regular expression to end of file
 sed -n '/regexp/,$p'

 # print section of file based on line numbers (lines 8-12, inclusive)
 sed -n '8,12p'               # method 1
 sed '8,12!d'                 # method 2

 # print line number 52
 sed -n '52p'                 # method 1
 sed '52!d'                   # method 2
 sed '52q;d'                  # method 3, efficient on large files

 # beginning at line 3, print every 7th line
 gsed -n '3~7p'               # GNU sed only
 sed -n '3,${p;n;n;n;n;n;n;}' # other seds

 # print section of file between two regular expressions (inclusive)
 sed -n '/Iowa/,/Montana/p'             # case sensitive

SELECTIVE DELETION OF CERTAIN LINES:

 # print all of file EXCEPT section between 2 regular expressions
 sed '/Iowa/,/Montana/d'

 # delete duplicate, consecutive lines from a file (emulates "uniq").
 # First line in a set of duplicate lines is kept, rest are deleted.
 sed '$!N; /^\(.*\)\n\1$/!P; D'

 # delete duplicate, nonconsecutive lines from a file. Beware not to
 # overflow the buffer size of the hold space, or else use GNU sed.
 sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P'

 # delete the first 10 lines of a file
 sed '1,10d'

 # delete the last line of a file
 sed '$d'

 # delete the last 2 lines of a file
 sed 'N;$!P;$!D;$d'

 # delete the last 10 lines of a file
 sed -e :a -e '$d;N;2,10ba' -e 'P;D'   # method 1
 sed -n -e :a -e '1,10!{P;N;D;};N;ba'  # method 2

 # delete every 8th line
 gsed '0~8d'                           # GNU sed only
 sed 'n;n;n;n;n;n;n;d;'                # other seds

 # delete ALL blank lines from a file (same as "grep '.' ")
 sed '/^$/d'                           # method 1
 sed '/./!d'                           # method 2

 # delete all CONSECUTIVE blank lines from file except the first; also
 # deletes all blank lines from top and end of file (emulates "cat -s")
 sed '/./,/^$/!d'          # method 1, allows 0 blanks at top, 1 at EOF
 sed '/^$/N;/\n$/D'        # method 2, allows 1 blank at top, 0 at EOF

 # delete all CONSECUTIVE blank lines from file except the first 2:
 sed '/^$/N;/\n$/N;//D'

 # delete all leading blank lines at top of file
 sed '/./,$!d'

 # delete all trailing blank lines at end of file
 sed -e :a -e '/^\n*$/{$d;N;ba' -e '}'  # works on all seds
 sed -e :a -e '/^\n*$/N;/\n$/ba'        # ditto, except for gsed 3.02*

 # delete the last line of each paragraph
 sed -n '/^$/{p;h;};/./{x;/./p;}'

SPECIAL APPLICATIONS:

 # remove nroff overstrikes (char, backspace) from man pages. The 'echo'
 # command may need an -e switch if you use Unix System V or bash shell.
 sed "s/.`echo \\\b`//g"    # double quotes required for Unix environment
 sed 's/.^H//g'             # in bash/tcsh, press Ctrl-V and then Ctrl-H
 sed 's/.\x08//g'           # hex expression for sed v1.5

 # get Usenet/e-mail message header
 sed '/^$/q'                # deletes everything after first blank line

 # get Usenet/e-mail message body
 sed '1,/^$/d'              # deletes everything up to first blank line

 # get Subject header, but remove initial "Subject: " portion
 sed '/^Subject: */!d; s///;q'

 # get return address header
 sed '/^Reply-To:/q; /^From:/h; /./d;g;q'

 # parse out the address proper. Pulls out the e-mail address by itself
 # from the 1-line return address header (see preceding script)
 sed 's/ *(.*)//; s/>.*//; s/.*[:<] *//'

 # add a leading angle bracket and space to each line (quote a message)
 sed 's/^/> /'

 # delete leading angle bracket & space from each line (unquote a message)
 sed 's/^> //'

 # remove most HTML tags (accommodates multiple-line tags)
 sed -e :a -e 's/<[^>]*>//g;/</N;//ba'

 # extract multi-part uuencoded binaries, removing extraneous header
 # info, so that only the uuencoded portion remains. Files passed to
 # sed must be passed in the proper order. Version 1 can be entered
 # from the command line; version 2 can be made into an executable
 # Unix shell script. (Modified from a script by Rahul Dhesi.)
 sed '/^end/,/^begin/d' file1 file2 ... fileX | uudecode   # vers. 1
 sed '/^end/,/^begin/d' "$@" | uudecode                    # vers. 2

 # zip up each .TXT file individually, deleting the source file and
 # setting the name of each .ZIP file to the basename of the .TXT file
 # (under DOS: the "dir /b" switch returns bare filenames in all caps).
 echo @echo off >zipup.bat
 dir /b *.txt | sed "s/^\(.*\)\.TXT/pkzip -mo \1 \1.TXT/" >>zipup.bat

TYPICAL USE: Sed takes one or more editing commands and applies all of
them, in sequence, to each line of input. After all the commands have
been applied to the first input line, that line is output and a second
input line is taken for processing, and the cycle repeats. The
preceding examples assume that input comes from the standard input
device (i.e, the console, normally this will be piped input). One or
more filenames can be appended to the command line if the input does
not come from stdin. Output is sent to stdout (the screen). Thus:

 cat filename | sed '10q'        # uses piped input
 sed '10q' filename              # same effect, avoids a useless "cat"
 sed '10q' filename > newfile    # redirects output to disk

For additional syntax instructions, including the way to apply editing
commands from a disk file instead of the command line, consult "sed &
awk, 2nd Edition," by Dale Dougherty and Arnold Robbins (O'Reilly,
1997; http://www.ora.com), "UNIX Text Processing," by Dale Dougherty
and Tim O'Reilly (Hayden Books, 1987) or the tutorials by Mike Arst
distributed in U-SEDIT2.ZIP (many sites). To fully exploit the power
of sed, one must understand "regular expressions." For this, see
"Mastering Regular Expressions" by Jeffrey Friedl (O'Reilly, 1997).
The manual ("man") pages on Unix systems may be helpful (try "man
sed", "man regexp", or the subsection on regular expressions in "man
ed"), but man pages are notoriously difficult. They are not written to
teach sed use or regexps to first-time users, but as a reference text
for those already acquainted with these tools.

QUOTING SYNTAX: The preceding examples use single quotes ('...')
instead of double quotes ("...") to enclose editing commands, since
sed is typically used on a Unix platform. Single quotes prevent the
Unix shell from intrepreting the dollar sign ($) and backquotes
(`...`), which are expanded by the shell if they are enclosed in
double quotes. Users of the "csh" shell and derivatives will also need
to quote the exclamation mark (!) with the backslash (i.e., \!) to
properly run the examples listed above, even within single quotes.
Versions of sed written for DOS invariably require double quotes
("...") instead of single quotes to enclose editing commands.

USE OF '\t' IN SED SCRIPTS: For clarity in documentation, we have used
the expression '\t' to indicate a tab character (0x09) in the scripts.
However, most versions of sed do not recognize the '\t' abbreviation,
so when typing these scripts from the command line, you should press
the TAB key instead. '\t' is supported as a regular expression
metacharacter in awk, perl, and HHsed, sedmod, and GNU sed v3.02.80.

VERSIONS OF SED: Versions of sed do differ, and some slight syntax
variation is to be expected. In particular, most do not support the
use of labels (:name) or branch instructions (b,t) within editing
commands, except at the end of those commands. We have used the syntax
which will be portable to most users of sed, even though the popular
GNU versions of sed allow a more succinct syntax. When the reader sees
a fairly long command such as this:

   sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d

it is heartening to know that GNU sed will let you reduce it to:

   sed '/AAA/b;/BBB/b;/CCC/b;d'      # or even
   sed '/AAA\|BBB\|CCC/b;d'

In addition, remember that while many versions of sed accept a command
like "/one/ s/RE1/RE2/", some do NOT allow "/one/! s/RE1/RE2/", which
contains space before the 's'. Omit the space when typing the command.

OPTIMIZING FOR SPEED: If execution speed needs to be increased (due to
large input files or slow processors or hard disks), substitution will
be executed more quickly if the "find" expression is specified before
giving the "s/.../.../" instruction. Thus:

   sed 's/foo/bar/g' filename         # standard replace command
   sed '/foo/ s/foo/bar/g' filename   # executes more quickly
   sed '/foo/ s//bar/g' filename      # shorthand sed syntax

On line selection or deletion in which you only need to output lines
from the first part of the file, a "quit" command (q) in the script
will drastically reduce processing time for large files. Thus:

   sed -n '45,50p' filename           # print line nos. 45-50 of a file
   sed -n '51q;45,50p' filename       # same, but executes much faster

If you have any additional scripts to contribute or if you find errors
in this document, please send e-mail to the compiler. Indicate the
version of sed you used, the operating system it was compiled for, and
the nature of the problem. Various scripts in this file were written
or contributed by:

 Al Aab <af137@freenet.toronto.on.ca>   # "seders" list moderator
 Edgar Allen <era@sky.net>              # various
 Yiorgos Adamopoulos <adamo@softlab.ece.ntua.gr>
 Dale Dougherty <dale@songline.com>     # author of "sed & awk"
 Carlos Duarte <cdua@algos.inesc.pt>    # author of "do it with sed"
 Eric Pement <pemente@northpark.edu>    # author of this document
 Ken Pizzini <ken@halcyon.com>          # author of GNU sed v3.02
 S.G. Ravenhall <stew.ravenhall@totalise.co.uk> # great de-html script
 Greg Ubben <gsu@romulus.ncsc.mil>      # many contributions & much help

 

-------------------------------------------------------------------------
SED单行脚本快速参考(Unix 流编辑器)                       2005年12月29日

英文标题:USEFUL ONE-LINE SCRIPTS FOR SED (Unix stream editor)
原标题:HANDY ONE-LINERS FOR SED (Unix stream editor)

整理:Eric Pement  - 电邮:pemente[at]northpark[dot]edu         版本5.5
译者:Joe Hong     - 电邮:hq00e[at]126[dot]com

在以下地址可找到本文档的最新(英文)版本:
   http://sed.sourceforge.net/sed1line.txt
   http://www.pement.org/sed/sed1line.txt

其他语言版本:
  中文          - http://sed.sourceforge.net/sed1line_zh-CN.html
  捷克语        - http://sed.sourceforge.net/sed1line_cz.html
  荷语          - http://sed.sourceforge.net/sed1line_nl.html
  法语          - http://sed.sourceforge.net/sed1line_fr.html
  德语          - http://sed.sourceforge.net/sed1line_de.html

  葡语          - http://sed.sourceforge.net/sed1line_pt-BR.html


文本间隔:
--------

 # 在每一行后面增加一空行
 sed G

 # 将原来的所有空行删除并在每一行后面增加一空行。
 # 这样在输出的文本中每一行后面将有且只有一空行。
 sed '/^$/d;G'

 # 在每一行后面增加两行空行
 sed 'G;G'

 # 将第一个脚本所产生的所有空行删除(即删除所有偶数行)
 sed 'n;d'

 # 在匹配式样“regex”的行之前插入一空行
 sed '/regex/{x;p;x;}'

 # 在匹配式样“regex”的行之后插入一空行
 sed '/regex/G'

 # 在匹配式样“regex”的行之前和之后各插入一空行
 sed '/regex/{x;p;x;G;}'

编号:
--------

 # 为文件中的每一行进行编号(简单的左对齐方式)。这里使用了“制表符”
 # (tab,见本文末尾关于'\t'的用法的描述)而不是空格来对齐边缘。
 sed = filename | sed 'N;s/\n/\t/'

 # 对文件中的所有行编号(行号在左,文字右端对齐)。
 sed = filename | sed 'N; s/^/     /; s/ *\(.\{6,\}\)\n/\1  /'

 # 对文件中的所有行编号,但只显示非空白行的行号。
 sed '/./=' filename | sed '/./N; s/\n/ /'

 # 计算行数 (模拟 "wc -l")
 sed -n '$='

文本转换和替代:
--------

 # Unix环境:转换DOS的新行符(CR/LF)为Unix格式。
 sed 's/.$//'                     # 假设所有行以CR/LF结束
 sed 's/^M$//'                    # 在bash/tcsh中,将按Ctrl-M改为按Ctrl-V
 sed 's/\x0D$//'                  # ssed、gsed 3.02.80,及更高版本

 # Unix环境:转换Unix的新行符(LF)为DOS格式。
 sed "s/$/`echo -e \\\r`/"        # 在ksh下所使用的命令
 sed 's/$'"/`echo \\\r`/"         # 在bash下所使用的命令
 sed "s/$/`echo \\\r`/"           # 在zsh下所使用的命令
 sed 's/$/\r/'                    # gsed 3.02.80 及更高版本

 # DOS环境:转换Unix新行符(LF)为DOS格式。
 sed "s/$//"                      # 方法 1
 sed -n p                         # 方法 2

 # DOS环境:转换DOS新行符(CR/LF)为Unix格式。
 # 下面的脚本只对UnxUtils sed 4.0.7 及更高版本有效。要识别UnxUtils版本的
 #  sed可以通过其特有的“--text”选项。你可以使用帮助选项(“--help”)看
 # 其中有无一个“--text”项以此来判断所使用的是否是UnxUtils版本。其它DOS
 # 版本的的sed则无法进行这一转换。但可以用“tr”来实现这一转换。
 sed "s/\r//" infile >outfile     # UnxUtils sed v4.0.7 或更高版本
 tr -d \r <infile >outfile        # GNU tr 1.22 或更高版本

 # 将每一行前导的“空白字符”(空格,制表符)删除
 # 使之左对齐
 sed 's/^[ \t]*//'                # 见本文末尾关于'\t'用法的描述

 # 将每一行拖尾的“空白字符”(空格,制表符)删除
 sed 's/[ \t]*$//'                # 见本文末尾关于'\t'用法的描述

 # 将每一行中的前导和拖尾的空白字符删除
 sed 's/^[ \t]*//;s/[ \t]*$//'

 # 在每一行开头处插入5个空格(使全文向右移动5个字符的位置)
 sed 's/^/     /'

 # 以79个字符为宽度,将所有文本右对齐
 sed -e :a -e 's/^.\{1,78\}$/ &/;ta'  # 78个字符外加最后的一个空格

 # 以79个字符为宽度,使所有文本居中。在方法1中,为了让文本居中每一行的前
 # 头和后头都填充了空格。 在方法2中,在居中文本的过程中只在文本的前面填充
 # 空格,并且最终这些空格将有一半会被删除。此外每一行的后头并未填充空格。
 sed  -e :a -e 's/^.\{1,77\}$/ & /;ta'                     # 方法1
 sed  -e :a -e 's/^.\{1,77\}$/ &/;ta' -e 's/\( *\)\1/\1/'  # 方法2

 # 在每一行中查找字串“foo”,并将找到的“foo”替换为“bar”
 sed 's/foo/bar/'                 # 只替换每一行中的第一个“foo”字串
 sed 's/foo/bar/4'                # 只替换每一行中的第四个“foo”字串
 sed 's/foo/bar/g'                # 将每一行中的所有“foo”都换成“bar”
 sed 's/\(.*\)foo\(.*foo\)/\1bar\2/' # 替换倒数第二个“foo”
 sed 's/\(.*\)foo/\1bar/'            # 替换最后一个“foo”

 # 只在行中出现字串“baz”的情况下将“foo”替换成“bar”
 sed '/baz/s/foo/bar/g'

 # 将“foo”替换成“bar”,并且只在行中未出现字串“baz”的情况下替换
 sed '/baz/!s/foo/bar/g'

 # 不管是“scarlet”“ruby”还是“puce”,一律换成“red”
 sed 's/scarlet/red/g;s/ruby/red/g;s/puce/red/g'  #对多数的sed都有效
 gsed 's/scarlet\|ruby\|puce/red/g'               # 只对GNU sed有效

 # 倒置所有行,第一行成为最后一行,依次类推(模拟“tac”)。
 # 由于某些原因,使用下面命令时HHsed v1.5会将文件中的空行删除
 sed '1!G;h;$!d'               # 方法1
 sed -n '1!G;h;$p'             # 方法2

 # 将行中的字符逆序排列,第一个字成为最后一字,……(模拟“rev”)
 sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//'

 # 将每两行连接成一行(类似“paste”)
 sed '$!N;s/\n/ /'

 # 如果当前行以反斜杠“\”结束,则将下一行并到当前行末尾
 # 并去掉原来行尾的反斜杠
 sed -e :a -e '/\\$/N; s/\\\n//; ta'

 # 如果当前行以等号开头,将当前行并到上一行末尾
 # 并以单个空格代替原来行头的“=”
 sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D'

 # 为数字字串增加逗号分隔符号,将“1234567”改为“1,234,567”
 gsed ':a;s/\B[0-9]\{3\}\>/,&/;ta'                     # GNU sed
 sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta'  # 其他sed

 # 为带有小数点和负号的数值增加逗号分隔符(GNU sed)
 gsed -r ':a;s/(^|[^0-9.])([0-9]+)([0-9]{3})/\1\2,\3/g;ta'

 # 在每5行后增加一空白行 (在第5,10,15,20,等行后增加一空白行)
 gsed '0~5G'                      # 只对GNU sed有效
 sed 'n;n;n;n;G;'                 # 其他sed

选择性地显示特定行:
--------

 # 显示文件中的前10行 (模拟“head”的行为)
 sed 10q

 # 显示文件中的第一行 (模拟“head -1”命令)
 sed q

 # 显示文件中的最后10行 (模拟“tail”)
 sed -e :a -e '$q;N;11,$D;ba'

 # 显示文件中的最后2行(模拟“tail -2”命令)
 sed '$!N;$!D'

 # 显示文件中的最后一行(模拟“tail -1”)
 sed '$!d'                        # 方法1
 sed -n '$p'                      # 方法2

 # 显示文件中的倒数第二行
 sed -e '$!{h;d;}' -e x              # 当文件中只有一行时,输入空行
 sed -e '1{$q;}' -e '$!{h;d;}' -e x  # 当文件中只有一行时,显示该行
 sed -e '1{$d;}' -e '$!{h;d;}' -e x  # 当文件中只有一行时,不输出

 # 只显示匹配正则表达式的行(模拟“grep”)
 sed -n '/regexp/p'               # 方法1
 sed '/regexp/!d'                 # 方法2

 # 只显示“不”匹配正则表达式的行(模拟“grep -v”)
 sed -n '/regexp/!p'              # 方法1,与前面的命令相对应
 sed '/regexp/d'                  # 方法2,类似的语法

 # 查找“regexp”并将匹配行的上一行显示出来,但并不显示匹配行
 sed -n '/regexp/{g;1!p;};h'

 # 查找“regexp”并将匹配行的下一行显示出来,但并不显示匹配行
 sed -n '/regexp/{n;p;}'

 # 显示包含“regexp”的行及其前后行,并在第一行之前加上“regexp”所
 # 在行的行号 (类似“grep -A1 -B1”)
 sed -n -e '/regexp/{=;x;1!p;g;$!N;p;D;}' -e h

 # 显示包含“AAA”、“BBB”或“CCC”的行(任意次序)
 sed '/AAA/!d; /BBB/!d; /CCC/!d'  # 字串的次序不影响结果

 # 显示包含“AAA”、“BBB”和“CCC”的行(固定次序)
 sed '/AAA.*BBB.*CCC/!d'

 # 显示包含“AAA”“BBB”或“CCC”的行 (模拟“egrep”)
 sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d    # 多数sed
 gsed '/AAA\|BBB\|CCC/!d'                        # 对GNU sed有效

 # 显示包含“AAA”的段落 (段落间以空行分隔)
 # HHsed v1.5 必须在“x;”后加入“G;”,接下来的3个脚本都是这样
 sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;'

 # 显示包含“AAA”“BBB”和“CCC”三个字串的段落 (任意次序)
 sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;/BBB/!d;/CCC/!d'

 # 显示包含“AAA”、“BBB”、“CCC”三者中任一字串的段落 (任意次序)
 sed -e '/./{H;$!d;}' -e 'x;/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d
 gsed '/./{H;$!d;};x;/AAA\|BBB\|CCC/b;d'         # 只对GNU sed有效

 # 显示包含65个或以上字符的行
 sed -n '/^.\{65\}/p'

 # 显示包含65个以下字符的行
 sed -n '/^.\{65\}/!p'            # 方法1,与上面的脚本相对应
 sed '/^.\{65\}/d'                # 方法2,更简便一点的方法

 # 显示部分文本——从包含正则表达式的行开始到最后一行结束
 sed -n '/regexp/,$p'

 # 显示部分文本——指定行号范围(从第8至第12行,含8和12行)
 sed -n '8,12p'                   # 方法1
 sed '8,12!d'                     # 方法2

 # 显示第52行
 sed -n '52p'                     # 方法1
 sed '52!d'                       # 方法2
 sed '52q;d'                      # 方法3, 处理大文件时更有效率

 # 从第3行开始,每7行显示一次    
 gsed -n '3~7p'                   # 只对GNU sed有效
 sed -n '3,${p;n;n;n;n;n;n;}'     # 其他sed

 # 显示两个正则表达式之间的文本(包含)
 sed -n '/Iowa/,/Montana/p'       # 区分大小写方式

选择性地删除特定行:
--------

 # 显示通篇文档,除了两个正则表达式之间的内容
 sed '/Iowa/,/Montana/d'

 # 删除文件中相邻的重复行(模拟“uniq”)
 # 只保留重复行中的第一行,其他行删除
 sed '$!N; /^\(.*\)\n\1$/!P; D'

 # 删除文件中的重复行,不管有无相邻。注意hold space所能支持的缓存
 # 大小,或者使用GNU sed。
 sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P'

 # 删除除重复行外的所有行(模拟“uniq -d”)
 sed '$!N; s/^\(.*\)\n\1$/\1/; t; D'

 # 删除文件中开头的10行
 sed '1,10d'

 # 删除文件中的最后一行
 sed '$d'

 # 删除文件中的最后两行
 sed 'N;$!P;$!D;$d'

 # 删除文件中的最后10行
 sed -e :a -e '$d;N;2,10ba' -e 'P;D'   # 方法1
 sed -n -e :a -e '1,10!{P;N;D;};N;ba'  # 方法2

 # 删除8的倍数行
 gsed '0~8d'                           # 只对GNU sed有效
 sed 'n;n;n;n;n;n;n;d;'                # 其他sed

 # 删除匹配式样的行
 sed '/pattern/d'                      # 删除含pattern的行。当然pattern
                                       # 可以换成任何有效的正则表达式

 # 删除文件中的所有空行(与“grep '.' ”效果相同)
 sed '/^$/d'                           # 方法1
 sed '/./!d'                           # 方法2

 # 只保留多个相邻空行的第一行。并且删除文件顶部和尾部的空行。
 # (模拟“cat -s”)
 sed '/./,/^$/!d'        #方法1,删除文件顶部的空行,允许尾部保留一空行
 sed '/^$/N;/\n$/D'      #方法2,允许顶部保留一空行,尾部不留空行

 # 只保留多个相邻空行的前两行。
 sed '/^$/N;/\n$/N;//D'

 # 删除文件顶部的所有空行
 sed '/./,$!d'

 # 删除文件尾部的所有空行
 sed -e :a -e '/^\n*$/{$d;N;ba' -e '}'  # 对所有sed有效
 sed -e :a -e '/^\n*$/N;/\n$/ba'        # 同上,但只对 gsed 3.02.*有效

 # 删除每个段落的最后一行
 sed -n '/^$/{p;h;};/./{x;/./p;}'

特殊应用:
--------

 # 移除手册页(man page)中的nroff标记。在Unix System V或bash shell下使
 # 用'echo'命令时可能需要加上 -e 选项。
 sed "s/.`echo \\\b`//g"    # 外层的双括号是必须的(Unix环境)
 sed 's/.^H//g'             # 在bash或tcsh中, 按 Ctrl-V 再按 Ctrl-H
 sed 's/.\x08//g'           # sed 1.5,GNU sed,ssed所使用的十六进制的表示方法

 # 提取新闻组或 e-mail 的邮件头
 sed '/^$/q'                # 删除第一行空行后的所有内容

 # 提取新闻组或 e-mail 的正文部分
 sed '1,/^$/d'              # 删除第一行空行之前的所有内容

 # 从邮件头提取“Subject”(标题栏字段),并移除开头的“Subject:”字样
 sed '/^Subject: */!d; s///;q'

 # 从邮件头获得回复地址
 sed '/^Reply-To:/q; /^From:/h; /./d;g;q'

 # 获取邮件地址。在上一个脚本所产生的那一行邮件头的基础上进一步的将非电邮
 # 地址的部分剃除。(见上一脚本)
 sed 's/ *(.*)//; s/>.*//; s/.*[:<] *//'

 # 在每一行开头加上一个尖括号和空格(引用信息)
 sed 's/^/> /'

 # 将每一行开头处的尖括号和空格删除(解除引用)
 sed 's/^> //'

 # 移除大部分的HTML标签(包括跨行标签)
 sed -e :a -e 's/<[^>]*>//g;/</N;//ba'

 # 将分成多卷的uuencode文件解码。移除文件头信息,只保留uuencode编码部分。
 # 文件必须以特定顺序传给sed。下面第一种版本的脚本可以直接在命令行下输入;
 # 第二种版本则可以放入一个带执行权限的shell脚本中。(由Rahul Dhesi的一
 # 个脚本修改而来。)
 sed '/^end/,/^begin/d' file1 file2 ... fileX | uudecode   # vers. 1
 sed '/^end/,/^begin/d' "$@" | uudecode                    # vers. 2

 # 将文件中的段落以字母顺序排序。段落间以(一行或多行)空行分隔。GNU sed使用
 # 字元“\v”来表示垂直制表符,这里用它来作为换行符的占位符——当然你也可以
 # 用其他未在文件中使用的字符来代替它。
 sed '/./{H;d;};x;s/\n/={NL}=/g' file | sort | sed '1s/={NL}=//;s/={NL}=/\n/g'
 gsed '/./{H;d};x;y/\n/\v/' file | sort | sed '1s/\v//;y/\v/\n/'

 # 分别压缩每个.TXT文件,压缩后删除原来的文件并将压缩后的.ZIP文件
 # 命名为与原来相同的名字(只是扩展名不同)。(DOS环境:“dir /b”
 # 显示不带路径的文件名)。
 echo @echo off >zipup.bat
 dir /b *.txt | sed "s/^\(.*\)\.TXT/pkzip -mo \1 \1.TXT/" >>zipup.bat


使用SED:Sed接受一个或多个编辑命令,并且每读入一行后就依次应用这些命令。
当读入第一行输入后,sed对其应用所有的命令,然后将结果输出。接着再读入第二
行输入,对其应用所有的命令……并重复这个过程。上一个例子中sed由标准输入设
备(即命令解释器,通常是以管道输入的形式)获得输入。在命令行给出一个或多
个文件名作为参数时,这些文件取代标准输入设备成为sed的输入。sed的输出将被
送到标准输出(显示器)。因此:

 cat filename | sed '10q'         # 使用管道输入
 sed '10q' filename               # 同样效果,但不使用管道输入
 sed '10q' filename > newfile     # 将输出转移(重定向)到磁盘上

要了解sed命令的使用说明,包括如何通过脚本文件(而非从命令行)来使用这些命
令,请参阅《sed & awk》第二版,作者Dale Dougherty和Arnold Robbins
(O'Reilly,1997;http://www.ora.com),《UNIX Text Processing》,作者
Dale Dougherty和Tim O'Reilly(Hayden Books,1987)或者是Mike Arst写的教
程——压缩包的名称是“U-SEDIT2.ZIP”(在许多站点上都找得到)。要发掘sed
的潜力,则必须对“正则表达式”有足够的理解。正则表达式的资料可以看
《Mastering Regular Expressions》作者Jeffrey Friedl(O'reilly 1997)。
Unix系统所提供的手册页(“man”)也会有所帮助(试一下这些命令
“man sed”、“man regexp”,或者看“man ed”中关于正则表达式的部分),但
手册提供的信息比较“抽象”——这也是它一直为人所诟病的。不过,它本来就不
是用来教初学者如何使用sed或正则表达式的教材,而只是为那些熟悉这些工具的人
提供的一些文本参考。

括号语法:前面的例子对sed命令基本上都使用单引号('...')而非双引号
("...")这是因为sed通常是在Unix平台上使用。单引号下,Unix的shell(命令
解释器)不会对美元符($)和后引号(`...`)进行解释和执行。而在双引号下
美元符会被展开为变量或参数的值,后引号中的命令被执行并以输出的结果代替
后引号中的内容。而在“csh”及其衍生的shell中使用感叹号(!)时需要在其前
面加上转义用的反斜杠(就像这样:\!)以保证上面所使用的例子能正常运行
(包括使用单引号的情况下)。DOS版本的Sed则一律使用双引号("...")而不是
引号来圈起命令。

'\t'的用法:为了使本文保持行文简洁,我们在脚本中使用'\t'来表示一个制表
符。但是现在大部分版本的sed还不能识别'\t'的简写方式,因此当在命令行中为
脚本输入制表符时,你应该直接按TAB键来输入制表符而不是输入'\t'。下列的工
具软件都支持'\t'做为一个正则表达式的字元来表示制表符:awk、perl、HHsed、
sedmod以及GNU sed v3.02.80。

不同版本的SED:不同的版本间的sed会有些不同之处,可以想象它们之间在语法上
会有差异。具体而言,它们中大部分不支持在编辑命令中间使用标签(:name)或分
支命令(b,t),除非是放在那些的末尾。这篇文档中我们尽量选用了可移植性较高
的语法,以使大多数版本的sed的用户都能使用这些脚本。不过GNU版本的sed允许使
用更简洁的语法。想像一下当读者看到一个很长的命令时的心情:

   sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d

好消息是GNU sed能让命令更紧凑:

   sed '/AAA/b;/BBB/b;/CCC/b;d'      # 甚至可以写成
   sed '/AAA\|BBB\|CCC/b;d'

此外,请注意虽然许多版本的sed接受象“/one/ s/RE1/RE2/”这种在's'前带有空
格的命令,但这些版本中有些却不接受这样的命令:“/one/! s/RE1/RE2/”。这时
只需要把中间的空格去掉就行了。

速度优化:当由于某种原因(比如输入文件较大、处理器或硬盘较慢等)需要提高
命令执行速度时,可以考虑在替换命令(“s/.../.../”)前面加上地址表达式来
提高速度。举例来说:

   sed 's/foo/bar/g' filename         # 标准替换命令
   sed '/foo/ s/foo/bar/g' filename   # 速度更快
   sed '/foo/ s//bar/g' filename      # 简写形式

当只需要显示文件的前面的部分或需要删除后面的内容时,可以在脚本中使用“q”
命令(退出命令)。在处理大的文件时,这会节省大量时间。因此:

   sed -n '45,50p' filename           # 显示第45到50行
   sed -n '51q;45,50p' filename       # 一样,但快得多

如果你有其他的单行脚本想与大家分享或者你发现了本文档中错误的地方,请发电
子邮件给本文档的作者(Eric Pement)。邮件中请记得提供你所使用的sed版本、 
该sed所运行的操作系统及对问题的适当描述。本文所指的单行脚本指命令行的长
度在65个字符或65个以下的sed脚本〔译注1〕。本文档的各种脚本是由以下所列作
者所写或提供:

 Al Aab                               # 建立了“seders”邮件列表
 Edgar Allen                          # 许多方面
 Yiorgos Adamopoulos                  # 许多方面
 Dale Dougherty                       # 《sed & awk》作者
 Carlos Duarte                        # 《do it with sed》作者
 Eric Pement                          # 本文档的作者
 Ken Pizzini                          # GNU sed v3.02 的作者
 S.G. Ravenhall                       # 去html标签脚本
 Greg Ubben                           # 有诸多贡献并提供了许多帮助
-------------------------------------------------------------------------

译注1:大部分情况下,sed脚本无论多长都能写成单行的形式(通过`-e'选项和`;'
号)——只要命令解释器支持,所以这里说的单行脚本除了能写成一行还对长度有
所限制。因为这些单行脚本的意义不在于它们是以单行的形式出现。而是让用户能
方便地在命令行中使用这些紧凑的脚本才是其意义所在。
posted @ 2014-08-22 14:07  alxe_yu  阅读(345)  评论(0)    收藏  举报