<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-124  評論-194  文章-0  trackbacks-0
    什么是sed?
    sed 是在 UNIX ® 操作系統(tǒng)上運(yùn)行的一個非交互式上下文編輯器。sed 被設(shè)計在下列三種情況下發(fā)揮作用:
    1) 編輯那些對舒適的交互式編輯而言太大的文件。
    2) 在編輯命令太復(fù)雜而難于在交互模式下鍵入的時候編輯任何大小的文件。
    3) 要在對輸入的一趟掃描中有效的進(jìn)行多個‘全局’編輯函數(shù)。
    因?yàn)槊看沃话演斎氲哪承┬旭v留在內(nèi)存中,并且不使用臨時文件,所以可編輯的文件的有效大小,只受限于輸入和輸出要同時共存于次級存儲的要求。
    可以單獨(dú)的建立復(fù)雜的編輯腳本并作為給 sed 的命令文件。對于復(fù)雜的編輯,這節(jié)省了可觀的鍵入和隨之而來的錯誤。從命令文件運(yùn)行 sed 高效于作者所知道的任何交互式編輯器,甚至包括能用預(yù)先寫好的腳本驅(qū)動的編輯器。

    sed是如何操作的?
    sed 缺省的把標(biāo)準(zhǔn)輸入復(fù)制到標(biāo)準(zhǔn)輸出,再把每行寫到輸出之前可能在其上進(jìn)行一個或多個編輯命令。這種行為可以通過命令行上的標(biāo)志來更改。
    sed編輯命令的一般格式為:
        [address]command [parameter]

    一個或兩個[address]是可以省略的;可以用任何數(shù)目的空白或 tab 把地址和函數(shù)分隔開。sed函數(shù)必須出現(xiàn)。依據(jù)給出的是哪個函數(shù),參數(shù)可能是必需的或是可選的。忽略在這些行開始處的 tab 字符和空格。

    sed如何對文件的行操作的步驟?
    1)sed對[address]里匹配的行,執(zhí)行命令并輸出在stdout。
    2)sed在對匹配的行的執(zhí)行完所有命令后,自動跳到下一個匹配行重復(fù)命令執(zhí)行。
    3)sed對文本行的操作,并不會更改文本的行內(nèi)容。sed是從文本中調(diào)出行內(nèi)容,并備份,然后在這備份上執(zhí)行sed命令,最終在stdout上輸出操作后的行。


    sed命令行格式和標(biāo)志:
    sed命令格式:sed [option] 'sed-script' file
    在命令行上option:
        * -n:告訴 sed 不復(fù)制所有的行,只復(fù)制 p 函數(shù)或在 s 函數(shù)后 p 標(biāo)志所指定的行。
        * -e:告訴 sed 把下一個參數(shù)接受為編輯命令。
        * -f:告訴 sed 把下一個參數(shù)接受為文件名;這個文件應(yīng)當(dāng)包含一行一個的編輯命令。

    什么是模式空間?
    模式匹配的范圍叫做模式空間。一般而言,模式空間是輸入文本中某一行,但是可以通過使用 N 命令把多于一行讀入模式空間

    sed如何從輸入文件里選擇編輯的行?
    編輯命令要應(yīng)用于其上的,輸入文件中的行可以通過地址來選擇。地址可以是行號或者是上下文地址。

    通過用花括號(‘{ }’)組合(group)命令,可以用一個地址(或地址對)來控制一組命令的應(yīng)用。

    sed的行號是十進(jìn)制整數(shù)。在從輸入讀入每一行的時候,增加一個行號計數(shù)器;行號地址匹配(選擇)導(dǎo)致這個內(nèi)部計數(shù)器等于地址行號的輸入行。計數(shù)器在多個輸入文件上累計運(yùn)行,在打開一個新文件的時候它不被復(fù)零(reset)。

    作為特殊情況,字符 $ 匹配輸入文件的最后一行。

    上下文地址是包圍在斜杠中(‘/’)的模式(‘正則表達(dá)式’)。sed 識別的正則表達(dá)式被構(gòu)造如下:
       * 1) 普通字符(不是下面討論的某個字符)是一個正則表達(dá)式,并且匹配這個字符。
        * 2) 在正則表達(dá)式開始處的‘^’符號(circumflex)匹配在行開始處的空(null)字符。
        * 3) 在正則表達(dá)式結(jié)束處的美元符號‘$’匹配在行結(jié)束處的空字符。
        * 4) 字符‘"n’匹配內(nèi)嵌的換行字符,而不是在模式空間結(jié)束處的換行。
        * 5) 點(diǎn)‘.’匹配除了模式空間的終止換行之外的任何字符。
        * 6) 跟隨著星號‘*’的正則表達(dá)式,匹配它所跟叢的正則表達(dá)式的任何數(shù)目(包括 0)的毗連出現(xiàn)。
        * 7) 在方括號‘[ ]’內(nèi)的字符串,匹配在字符串內(nèi)的任何字符,而非其他。但是如果這個字符串的第一個字符是‘^’符號,正則表達(dá)式匹配除了在這個字符串內(nèi)的字符和模式空間的終止換行之外的任何字符。
        * 8) 正則表達(dá)式的串聯(lián)(concatenation)是正則表達(dá)式,它匹配這個正則表達(dá)式的成員所匹配的字符串的串聯(lián)。
        * 9) 在順序的‘"(’和‘")’之間的正則表達(dá)式,在效果上等同于沒有它修飾的正則表達(dá)式,但它有個副作用,將在下面的 s 命令和緊后面的規(guī)定 10 中描述。
        * 10) 表達(dá)式‘"d’意味著與在同一個表達(dá)式中先前的‘"(’和‘")’中包圍的表達(dá)式所匹配的那些字符同樣的字符串。這里的 d 是一個單一的數(shù)字;指定的字符串是‘"(’的從左至右的第 d 個出現(xiàn)所起始的字符串。例如,表達(dá)式‘^"(.*")"1’匹配開始于同一個字符串的兩次重復(fù)出現(xiàn)的行。
        * 11) 孤立的空正則表達(dá)式(就是‘//’)等價于編譯的最后一個正則表達(dá)式。

    注意:要使用正則表達(dá)式的元字符(^ $ . * [ ] " /)中的某一個字符作為文字(去匹配輸入中它們自身的出現(xiàn)),要對這個特殊字符前導(dǎo)一個反斜杠‘"’。

    有的sed命令可能有 0,1 或 2 個地址。在每個命令中都給出了允許的地址的最大數(shù)目。地址多于最大允許個數(shù)的命令被認(rèn)為是錯誤的。

    如果命令沒有地址,它應(yīng)用于輸入中每個行。
    如果命令有一個地址,它應(yīng)用于匹配這個地址的所有行。
    如果命令有兩個地址,它應(yīng)用于匹配第一個地址的第一行,和直到(并包括)匹配第二個地址的第一個后續(xù)行的所有后續(xù)行。接著在后續(xù)的行上再次嘗試匹配第一個地址,并重復(fù)這個處理。兩個地址用逗號分隔。
    例子:
        /an/         匹配我們樣例文本的第 1, 3, 4 行
        /an.*an/     匹配第 1 行
        /^an/        沒有匹配行
        /./          匹配所有行
        /"./         匹配第 5 行
        /r*an/       匹配第 1,3, 4 行(number = zero!)
        /"(an").*"1/ 匹配第 1 行


    sed的命令格式:
    [address1]command

    [address1],[address2]command

    前者表示sed對匹配地址的行進(jìn)行操作
    后者表示sed對從匹配地址1的行到匹配地址2的行之間(包括地址1和地址2行)所有的行進(jìn)行操作

    另外sed命令還可以用大括號進(jìn)行分組,使其作用于同一個地址:
    [address]{
        command1
        command2
        command3
    }


    [address]{command1;command2;command3}

    注意:sed的[address]是正則表達(dá)式,并且要用/ /限定范圍,如:
    /^$/,/^ */d

    如果sed命令之間用;分隔,可以將多個命令寫在同一行,如:n;d;s/sdfd//g

    sed腳本的注釋行第一個字符必須是"#"號,如:
    #wstar.scd:xxxx

    sed的命令函數(shù):

    sed命令集由25個命令組成,而且sed的命令大多是用單個字符表示。

    n(讀取下一行)
    [address]n

    讀取[address]匹配行的下一行
    n命令改變了正常的流控制,導(dǎo)致輸入的下一行取代模式空間中的當(dāng)前行,如:
    /^".H1/{n;/^$/d}      #將匹配匹配^".H1的下一空行刪除

    =(打印行號)
    [address]=

    在stdout,打印匹配的行號,如:
    /   if/{
    =;p
    }

    p(打印行):
    /address/p

    在stdout,打印匹配的行

    d(刪除):
    [address]d

    如果模行匹配address,那么就刪除整個這一行
    [address1],[address2]d
    刪除匹配address1和address2中間的所有行
    注意:不允許在被刪除的行上做進(jìn)一步的操作
    例子:
    /^".sp/d
    /^&/,/^".bp/d

    a(追加新行):
    [address]a"
    text

    在匹配address的行后追加新的text行。
    注意:必須是a命令后跟一個"用于轉(zhuǎn)義第一個行尾,text必須從下一行開始。
    例子:
    /<larry's address>/a"
    4700 Cross Court"
    Freach tjck,IN

    i(插入新行):
    [address]ni"
    text

    表示在匹配address的行前插入新的text行。

    ni"
    text

    表示在第n行插入新的text行

    注意:必須是i命令后跟一個"用于轉(zhuǎn)義第一個行尾,text必須從下一行開始。
    例子:
    /<larry's address>/i"
    4700 Cross Court

    2i"
    .so macros"
    .ds CH first draft

    q(退出命令):
    [address]q

    退出命令q會使sed停止讀取新的輸入行(并停止將他們發(fā)送到輸出)
    /^".".$/q

    nq
    向stdout輸出1到(n-1)行的內(nèi)容,到第n行時退出sed
    sed '100q' test

    c(行更改):
    [address]c"
    text


    [address1],[address2]c"
    text

    注意:必須是i命令后跟一個"用于轉(zhuǎn)義第一個行尾,text必須從下一行開始
    c命令刪除當(dāng)前行并且在該位置放置所提供的文本。當(dāng)想要匹配行并整個取代它時使用c命令。
    /^".sp/c"
    .sp .5

    /^From/,/^$/{
    s/^From//p
    c"
    <Mail Header Removed>
    }

    y(轉(zhuǎn)換):
    轉(zhuǎn)換語法:y/charators/change-charactors/

    y的轉(zhuǎn)換是根據(jù)字符的位置來進(jìn)行的,//里用的不是正則表達(dá)式,只是一般的字符序列。它沒有詞的概念,只是簡單的將對應(yīng)位置上的字符作替換。
    注意:charactors和change-charactors的字符數(shù)目要一致
    y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/

    s(替換):
    替換命令語法為[address]s/pattern/replacement/flags

    修飾替換標(biāo)志flags是:
    n     1-512之間的一個數(shù)字,表示在模式空間里對匹配pattern的字符串第n次出現(xiàn)后開始進(jìn)行替換,將替換后的行輸出stdout
    g     對模式空間里匹配pattern的字符串進(jìn)行全局替換,將替換后的行輸出stdout
    p     將匹配行的內(nèi)容替換后輸出stdout
    w file 將模式空間內(nèi)容寫到文件file中
    替換命令s應(yīng)用于與[address]匹配的行。如果沒有指定行,那么就應(yīng)用于與pattern匹配的所有行。

    在repalcement里可以利用&符號,表示在替換字符串中引用pattern整個匹配內(nèi)容,如:
    s/See Section [1-9][0-9]*".[1-9][0-9]*/(&)/         #給匹配的字符串添加小括號()

    sed的控制流函數(shù):
    !(非匹配)
    [address]!command   #在不匹配的行,執(zhí)行sed命令

    [address1],[address2]!command
    非命令導(dǎo)致(寫在同一行上的)下一個命令,應(yīng)用到所有的且只能是未被地址部分選擇到那些輸入行上。
    /^$/!d
    #刪除不是空行的所有行

    {(命令集)
        組合命令‘{’導(dǎo)致下一組命令作為一個塊而被應(yīng)用(或不應(yīng)用)到組合命令的地址所選擇的輸入行上。在組合控制下的的命令中的第一個命令可以出現(xiàn)在與‘{’相同的一行或下一行上。
        組合的命令由自己獨(dú)立在一行之上的相匹配的‘}’終止。
        組合可以嵌套。

    :label(標(biāo)簽)
    標(biāo)簽是任意不多于7個字符的序列。標(biāo)簽本身占據(jù)一行并以冒號開始:,如:
    :mylabel
    標(biāo)簽將被分支b和測試t命令調(diào)用,改變sed控制流。
    b mylabel
    注意不要在標(biāo)簽后插入空格

    b(分支)
    branch命令用于腳本將控制權(quán)轉(zhuǎn)移別處。

    [address]b <label>
    label是可選的,如果沒有給出label,sed對該行的控制流就會自動轉(zhuǎn)移到結(jié)尾處。如果有l(wèi)abel就繼續(xù)執(zhí)行標(biāo)簽后的行。
    例子:
    /^".ES/,/^".EE/b
    s/^"/''/
    s/^$/''/
    ...
    s/@DQ@/"/g

    :top
    command1
    commnd2
    /pattern/b top
    command3
    #模式pattern不匹配時,sed執(zhí)行command1,command2,command3
    #模式pattern匹配時,控制流會跳轉(zhuǎn)到標(biāo)簽top處,sed執(zhí)行command1,command2,command1,command2,command3

    command1
    /pattern/b end
    command2
    :end
    command3
    #模式pattern不匹配時,sed執(zhí)行command1,command2,command3
    #模式pattern匹配時,sed執(zhí)行command1,command3

    t(測試是否成功替換)
    test命令用于判斷當(dāng)前匹配的地址上是否進(jìn)行了成功替換?成功替換sed的控制流就轉(zhuǎn)到標(biāo)簽。

    [address]t <label>
    label是可選的,如果沒有給出label,sed對該行的控制流就會自動轉(zhuǎn)移到結(jié)尾處。如果有l(wèi)abel就繼續(xù)
    例子:
    /".Rh 0/{
    s/""(.*")"/"2,"3/g
    t break
    s/""(.*")"/"1,"2/g
    t break
    ...
    break:
    more commands
    }
    #若該行有替換,則直接跳到break標(biāo)簽處執(zhí)行下邊命令


    匹配多行:

    假設(shè)我們的目標(biāo)文件test內(nèi)容是這樣的:

    file content
    aabbcc<<<comment part 1
    comment part 2>>>
    ddeeff

    現(xiàn)在需要把<<<...>>>這一段替換為“COMMENT”,那么sed語法應(yīng)當(dāng)是:

    :begin
    /<<</,/>>>/ {
    />>>/! {
    $! {
    N;
    b begin
    }
    }
    s/<<<.*>>>/COMMENT/;
    }

    上述語句存儲在test.sed中,那么執(zhí)行的方式和結(jié)果就是:

    $ sed -f test.sed test
    file content
    aabbccCOMMENT
    ddeeff

    把正則直接寫到命令里面也可以,用“;”來分隔命令即可:

    $ sed -e ":begin; /<<</,/>>>/ { />>>/! { $! { N; b begin }; }; s/<<<.*>>>/COMMENT/; };" test
    file content
    aabbccCOMMENT
    ddeeff

    注意右花括號之后也要加上分號“;”,如果再加上-i參數(shù)就可以直接把改動寫到原文件中去了。

    怎么樣?看懂了么?我來詳細(xì)說明吧,看那個多行命令的test.sed文件的內(nèi)容:

    • 首先花括號{}代表命令塊的開始,類似c的語法,后面就不再說了。

    • :begin,這是一個標(biāo)號,man中叫做label,也就是跳轉(zhuǎn)標(biāo)記,供b和t命令用,本例中使用了b命令。

    • /<<</,/>>>/,這是一個地址范圍(Addresses),后面 {}中的命令只對地址范圍之間的內(nèi)容使用。其中逗號前面的部分是開始地址,逗號后面是結(jié)束地址,都是正則表達(dá)式。由于sed是“流”式“行”處理,所以結(jié) 束地址是可以省略的,即如果地址的結(jié)束范圍不存在,那么將一直處理到文件結(jié)尾。本例中使用這個地址范圍主要是縮小處理的數(shù)據(jù)量,因?yàn)殡m然后面用N命令把對 一行的處理擴(kuò)展為了多行,但如果從文件開頭一直N擴(kuò)展到<<<出現(xiàn)為止,buffer中要處理的字符串可能會很長,影響效率。所以去掉 這個處理范圍也是能夠得到正確結(jié)果的,比如:

      $ sed -e ":begin; { />>>/! { $! { N; b begin }; }; s/<<<.*>>>/COMMENT/; };" test
      or
      $ sed -e "{:begin; />>>/! { $! { N; b begin }; }; s/<<<.*>>>/COMMENT/; };" test
    • />>>/!>>>是要替換內(nèi)容的結(jié)束標(biāo)記,帶上!就是說當(dāng)一行處理完畢之后,如果沒有發(fā)現(xiàn)結(jié)束標(biāo)記。。。

    • $!$在正則中表示字符串結(jié)尾,在sed中代表文件的最后一行,本句和上一句結(jié)合起來的意思就是:如果在本行沒有發(fā)現(xiàn)結(jié)束標(biāo)記,并且當(dāng)前掃描過的行并不是文件的最后一行。

    • N;,把下一行的內(nèi)容追加(append)到緩沖區(qū)(pattern)之后,在我們的例子中,在處理aabbcc<<<comment part 1這一行的內(nèi)容時,就會執(zhí)行到這里,然后把下一行的內(nèi)容comment part 2>>>一起放入緩沖區(qū),相當(dāng)于“合并”成了一行(sed的緩沖區(qū)中默認(rèn)都只會包含一行的內(nèi)容)。

    • b begin,由于仍然沒有找到結(jié)束標(biāo)記<<<(注意上一條說的緩沖區(qū)還沒有被處理),所以在這里跳回到標(biāo)號begin,重新開始命令。如果開始和結(jié)束標(biāo)記之間間隔了多行,那么就會有多次跳轉(zhuǎn)發(fā)生。

    • s/<<<.*>>>/COMMENT/;,終于,/>>>/!不再匹配成功,也就是我們已經(jīng)找到了結(jié)束標(biāo)記,那么用s命令來進(jìn)行替換。如果開始和結(jié)束標(biāo)記在一行的話,就會越過上面那些復(fù)雜的處理,直接執(zhí)行到這里了。

    轉(zhuǎn)自:
    http://www.fwolf.com/blog/post/346
    http://hi.baidu.com/hellolinuxworld/blog/item/5e3aa7080e6350c63bc76309.html


    posted on 2009-09-01 10:12 我愛佳娃 閱讀(3973) 評論(1)  編輯  收藏 所屬分類: 工具使用

    評論:
    # re: SED最佳參考[未登錄] 2009-11-23 20:02 | fly
    找了很久,這篇非常好。感謝分享啊。。  回復(fù)  更多評論
      
    主站蜘蛛池模板: 18pao国产成视频永久免费| 亚洲视频在线观看地址| 亚洲日韩精品国产3区| 99无码人妻一区二区三区免费| 亚洲激情黄色小说| 毛片在线免费视频| 亚洲日本久久一区二区va| 国国内清清草原免费视频99| 亚洲av日韩综合一区久热| 啦啦啦www免费视频| 亚洲精品伦理熟女国产一区二区| 免费国产成人午夜私人影视| 黄色一级毛片免费| 国产亚洲色视频在线| 国产一级淫片a免费播放口| 亚洲天堂在线播放| 无人在线观看免费高清视频| 羞羞网站免费观看| 亚洲日本一线产区和二线 | 18gay台湾男同亚洲男同| 国产亚洲老熟女视频| 免费在线黄色网址| 在线观看亚洲免费| 精品一区二区三区高清免费观看 | 偷自拍亚洲视频在线观看| 亚洲国产精品无码久久久不卡| 69免费视频大片| 国产一区二区免费视频| 国产精品免费一区二区三区| 亚洲精品在线网站| 亚洲毛片在线观看| 亚洲国产人成在线观看69网站 | 亚洲熟妇成人精品一区| 亚洲日韩激情无码一区| 久九九精品免费视频| 国产成人精品免费视频动漫| 无套内谢孕妇毛片免费看看| 亚洲第一页中文字幕| 久久久久久亚洲AV无码专区| 亚洲成片观看四虎永久| 久久国产高潮流白浆免费观看|