sed命令使用详解(下篇)

替换
详细的语法:
[address]s/pattern/replacement/flags
 
这里修饰替换的标志flags是:
n  1到512之间的一个数字,表示对本模式中指定模式第n次出现的情况进行替换。
g  对模式空间的所有出现的情况进行全局更改。而没有g时通常只有第一次出现的情况被取代。
p  打印模式空间的内容。
w file  将模式空间的内容写入到文件file中。
 
    替换命令应用于address匹配的行。如果没有指定地址,那么就应用过于pattern匹配的所有行。如果正则表达式作为地址来提供,并且没有指定模式,那么替换命令匹配由地址匹配的内容。
    replacement 是一个字符串,用来替换与正则表达式匹配的内容。在replacement 部分,
在replacement n 是一个数字,在replacement部分,在replacement部分,只有下列字符有特殊含义:
    &  在替换字符串中引用正则表达式匹配的内容。
    \n 匹配1是一个子串(n是一个数字),这个子串以前在pattern中用"\(" 和 "\)"指定。
    \  当在替换部分包含"与"符号(&),反斜杠(\)和替换命令的定界符时可用\转移他们。另外,它用于转移换行符并创建多行replacement字符串。
 
    flag可以组合使用,只要有意义。例如,gp表示对行进行全部替换并打印一行。至今为止,全局标志是最常用的。没有它,替换只能在行的第一次出现的位置执行。
 
  替换元字符
    & “与”符号用于在替换字符串中引用整个匹配内容。
    例如:
    s/Unix/(&)/g
    如果输入的内容为:on the Unix Operation System.
    那么替换命令将产生:On the (Unix) Operation System.
 
    \(\) \n 匹配字符串中的转义括号和替换字符串中\n (n表示1-9的数字)的组合使用。
    \(\)“转义括号”用于选择被匹配的字符串的任意独立部分,并在替换字符串中用\n来回调它。在sed中转义的圆括号括住正则表达式的任意部分并且保存它以备回调。一行允许最多保存9次。“\n”用于回调被保存的匹配部分,n是从1-9的数字,用于引用前面保存的备用字符串。
    例如:s/\(See Section \)/\([1-9][0-9]*\.[1-9][0-9]*\)/\2   \1/
 
 
  删除命令
    删除命令(d),如果某行匹配这个模式,那么就删除整个行,而不只是删除行中匹配的部分(要删除行的一部分,可以使用替换命令并指定一个空的替换)。
    例如:
    /^$/d 删除所有的空行
 
  追加、插入和更改   
    追加 a、插入 i 和 更改 c 命令提供了编辑器(例如vi)中执行的编辑功能。
 
    语法如下:
    追加[line-address]a\
    test
    插入[line-address]i\
    text
    更改[address]c\
    text
 
    插入命令将所提供的文本放置在模式空间的当前行之前。
    追加命令将文本放置在当前行之后。
    更改命令用所提供的文本取代模式空间的内容。
 
    例如:sed "/Title.*/i\
    insert text1\
    insert text2\
    insert text3" text1.txt
    该插入命令在匹配Title的行的前面插入3行文本。
   
    更改命令(不常用):追加命令和插入命令只应用于单个行地址,而不是一个范围内的行。然而,更改命令可以处理一个范围内的行。它删除这个范围中的所有行,但是提供的文本只被输出一次。例如:
    /^From /,/^$/c\
    <mail header Removed>
    删除整个邮件消息头并用<mail header Removed>取代它。注意当更改命令作为一组命令之一被封闭在大括号中并作用于一个范围内的行时,它将具有相反的功能。例如:
    /^From /,/^$/{
        s/^From //p
        c\
    <mail header Removed>
    }
    这个范围内的如果有10行匹配,这个示例就会输出10次“<mail header Removed>”。
 
   
    插入一个页眉:
    sed "1i\
        this is a head
        " test1.txt
    这里1表示文件的第一行,i是插入命令。
 
   插入一个页脚:
    sed "$a\
        this is a foot
        " test1.txt
    这里$表示文件的最后一行,a是追加命令
 
   同时候插入页眉和页脚:
    sed 'li\
         HEAD
         $a\
         FOOT
        ' test1.txt
   同时使用插入命令和追加命令:
    sed '/gaofeng1/i\
        in head1\
        in head2
        /gaofeng3/a\
        in foot1\
        in foot2
        ' test1.txt
 
  更改命令用所提供的文本取代模式空间的内容。实际上,它删除当前行并且在该位置放置所提供的文本。当想要匹配行,并且取代整个行时可以使用这个命令。
    例如:
    sed '/^\.sp/c\
    .sp .5
    ' test1.txt
    该命令将匹配.sp的行全部替换为.sp .5。
 
   列表
    列表命令(l)用于显示模式空间的内容,将非打印的字符显示为两个数字的ASCII代码。
    其功能类似于vi中的列表命令(:l)。可以使用该命令来检测输入中的“不可见”字符。
    例如:
    sed -n -e "l" test/spchar
 
   
   转换
 
   这个命令按位置将字符串abc中的每个字符,都转换成字符串xyz中的等价字符。它的语法如下:
    [address]y/abc/xyz/
    替换根据字符的位置来进行。因此,它没有“词”的概念。这样,在该行上的热河地方的"a"都被换成了"x",而不管他后面是否跟有"b"。这个命令的一个可能的用处是用大写字母替换对应的小写字母。这个命令影响整个模式空间的所有内容。
 
   打印命令(p)
  
   打印命令(p) 输出模式空间的内容。它既不清除模式空间也不改变脚本中的控制流。然而,它频繁地用在改变流控制的命令(d,N,b)之前。除非抑制(-n)默认的输出,否则打印命令将输出行的重复复制。
    下面我们看一个如何使用打印命令来进行调试脚本,它用于显示在发生改变之前行时什么样的。
    #在行改变之前打印原始行
    /^\.Ah/{
     p
     s/"//g
     s/^\.Ah//p
    }
 
  下面是运行上面脚本的一个例子:
    $sed -f sed.debug test1
    .Ah "Comment"
    Comment
    .Ah "Substitution"
    Substatution
    .Ah "Delete"
    Delete
    每个受影响的行都被打印了两次。
 
    打印行号(=)
 
    跟着地址后面的等号(=) 打印被匹配的行的行号。除非抑制行的自动输出,行号和行本身被打印。它的语法如下:
    [line-address]=
    该命令不能对一个范围的行进行操作。
    例如:
    #打印具有if语句的行号和行
    /if/{
        =
    }
    在寻找有编辑器报告的问题时,行号是非常有用的,编辑器通常列出行号。
 
    下一步
 
    下一步(next)命令(n)输出模式空间的内容,然后读取输入的下一行,而不用返回到脚本的顶端。它的语法如下:
    [address]n
    n命令总是应用于匹配行的下一行命令。
    例如下面脚本删除H1下面的空行:
    /^\.H1/{
     n
     /^$/d
    }
    可以按下面的方式阅读这个脚本:“匹配任何以字符串'.H1'开始的汗个,然后打印那一行并且读入下一行。如果下一行为空,在删除它”。大括号用于在同一个地址应用多个命令。
   
    读和写文件
 
    读(r)和写(w)命令用于直接处理文件。这两个命令都只有一个参数,即文件名。
 
    语法如下:
    [line-address]r file
    [address]w file
   
    例如:
    /^<company-list>/r company.txt
    当sed匹配以字符串"<company-list>"开始的行时,它将文件company.txt的内容附加在被匹配的行的末尾。后面的命令不会影响到从这个文件中读取的行,也就是不能对所读取到的内容作任何改变。
 
    写命令,是从一个文件中提取信息并将它放置在另一个文件中。
    例如:
    Adams,Henrietta    Northeast
    Banks,Freda        South
    Dennis,Jim         Midwest
    Garvey,Bill        Northeast
    Sommes,Tom         South
 
    我们可以按区域(第二列)分组,然后把他们分别放到3个文件中。
    /Northeast$/w testw1.txt
    /South$/w testw2.txt
    /Midwest$/w testw3.txt
 
    ok,上个例子进行的很顺利,那么,也许我们还想在写入到文件之前删除地区的名字。
    例如:/Northeast$/{
            s///
            w testw1.txt
          }