sed 是十分強大和小巧的文本流編輯器。在本文章系列的第二篇中,Daniel Robbins" name="description" />

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • sed 實例,第 2 部分

    發表于:2007-07-04來源:作者:點擊數: 標簽:
    通用線程 -- sed 實例,第 2 部分 轉載自:IBM developerWorks 中國網站 java script:window.open(this.src);" style="CURSOR: pointer" onload="return imgzoom(this,550)"> sed 是十分強大和小巧的文本流編輯器。在本文章系列的第二篇中,Daniel Robbins
    通用線程 -- sed 實例,第 2 部分
           
        轉載自:IBM developerWorks 中國網站

    javascript:window.open(this.src);" style="CURSOR: pointer" onload="return imgzoom(this,550)">
    sed 是十分強大和小巧的文本流編輯器。在本文章系列的第二篇中,Daniel Robbins 為您演示如何使用 sed 來執行字符串替換、創建更大的 sed 腳本以及如何使用 sed 的附加、插入和更改行命令。

    sed 是很有用(但常被遺忘)的 UNIX 流編輯器。在以批處理方式編輯文件或以有效方式創建 shell 腳本來修改現有文件方面,它是十分理想的工具。本文是前一篇介紹 sed 文章的續篇。

    替換!
    讓我們看一下 sed 最有用的命令之一,替換命令。使用該命令,可以將特定字符串或匹配的規則表達式用另一個字符串替換。下面是該命令最基本用法的示例:

     $ sed -e 's/foo/bar/' myfile.txt 

    上面的命令將 myfile.txt 中每行第一次出現的 'foo'(如果有的話)用字符串 'bar' 替換,然后將該文件內容輸出到標準輸出。請注意,我說的是每行第一次出現,盡管這通常不是您想要的。在進行字符串替換時,通常想執行全局替換。也就是說,要替換每行中的所有出現,如下所示:

    $ sed -e 's/foo/bar/g' myfile.txt 

    在最后一個斜杠之后附加的 'g' 選項告訴 sed 執行全局替換。

    關于 's///' 替換命令,還有其它幾件要了解的事。首先,它是一個命令,并且只是一個命令,在所有上例中都沒有指定地址。這意味著,'s///' 還可以與地址一起使用來控制要將命令應用到哪些行,如下所示:

     $ sed -e '1,10s/enchantment/entrapment/g' myfile2.txt 

    上例將導致用短語 'entrapment' 替換所有出現的短語 'enchantment',但是只在第一到第十行(包括這兩行)上這樣做。

     $ sed -e '/^$/,/^END/s/hills/mountains/g' myfile3.txt 

    該例將用 'mountains' 替換 'hills',但是,只從空行開始,到以三個字符 'END' 開始的行結束(包括這兩行)的文本塊上這樣做。

    關于 's///' 命令的另一個妙處是 '/' 分隔符有許多替換選項。如果正在執行字符串替換,并且規則表達式或替換字符串中有許多斜杠,則可以通過在 's' 之后指定一個不同的字符來更改分隔符。例如,下例將把所有出現的 /usr/local 替換成 /usr:

     $ sed -e 's:/usr/local:/usr:g' mylist.txt 

    在該例中,使用冒號作為分隔符。如果需要在規則表達式中指定分隔符字符,可以在它前面加入反斜杠。

    規則表達式混亂
    目前為止,我們只執行了簡單的字符串替換。雖然這很方便,但是我們還可以匹配規則表達式。例如,以下 sed 命令將匹配從 '<' 開始、到 '>' 結束、并且在其中包含任意數量字符的短語。下例將刪除該短語(用空字符串替換):

     $ sed -e 's/<.*>//g' myfile.html 

    這是要從文件除去 HTML 標記的第一個很好的 sed 腳本嘗試,但是由于規則表達式的特有規則,它不會很好地工作。原因何在?當 sed 試圖在行中匹配規則表達式時,它要在行中查找最長的匹配。在我的

    前一篇 sed 文章中,這不成問題,因為我們使用的是 'd' 和 'p' 命令,這些命令總要刪除或打印整行。但是,在使用 's///' 命令時,確實有很大不同,因為規則表達式匹配的整個部分將被目標字符串替換,或者,在本例中,被刪除。這意味著,上例將把下行:
     <b>This</b> is what <b>I</b> meant. 

    變成:

     meant. 

    我們要的不是這個,而是:

     This is what I meant. 

    幸運的是,有一種簡便方法來糾正該問題。我們不輸入“'<' 字符后面跟有一些字符并以 '>' 字符結束”的規則表達式,而只需輸入一個“'<' 字符后面跟有任意數量非 '>' 字符并以 '>' 字符結束”的規則表達式。這將與最短、而不是最長的可能性匹配。新命令如下:

     $ sed -e 's/<[^>]*>//g' myfile.html 

    在上例中,'[^>]' 指定“非 '>'”字符,其后的 '*' 完成該表達式以表示“零或多個非 '>' 字符”。對幾個 html 文件測試該命令,將它們管道輸出到 "more",然后仔細查看其結果。

    更多字符匹配
    '[ ]' 規則表達式語法還有一些附加選項。要指定字符范圍,只要字符不在第一個或最后一個位置,就可以使用 '-',如下所示:

     '[a-x]*' 

    這將匹配零或多個全部為 'a'、'b'、'c'...'v'、'w'、'x' 的字符。另外,可以使用 '[:space:]' 字符類來匹配空格。以下是可用字符類的相當完整的列表:

    字符類描述
    [:alnum:]字母數字 [a-z A-Z 0-9]
    [:alpha:]字母 [a-z A-Z]
    [:blank:]空格或制表鍵
    [:cntrl:]任何控制字符
    [:digit:]數字 [0-9]
    [:graph:]任何可視字符(無空格)
    [:lower:]小寫 [a-z]
    [:print:]非控制字符
    [:punct:]標點字符
    [:space:]空格
    [:upper:]大寫 [A-Z]
    [:xdigit:]十六進制數字 [0-9 a-f A-F]

    盡可能使用字符類是很有利的,因為它們可以更好地適應非英語 locale(包括某些必需的重音字符等等).

    高級替換功能
    我們已經看到如何執行簡單甚至有些復雜的直接替換,但是 sed 還可以做更多的事。實際上可以引用匹配規則表達式的部分或全部,并使用這些部分來構造替換字符串。作為示例,假設您正在回復一條消息。下例將在每一行前面加上短語 "ralph said: ":

     $ sed -e 's/.*/ralph said: &/' origmsg.txt 

    輸出如下:

     ralph said: Hiya Jim, ralph said: ralph said: 
    I sure like this sed stuff! ralph said:

    該例的替換字符串中使用了 '&' 字符,該字符告訴 sed 插入整個匹配的規則表達式。因此,可以將與 '.*' 匹配的任何內容(行中的零或多個字符的最大組或整行)插入到替換字符串中的任何位置,甚至多次插入。這非常好,但 sed 甚至更強大。

    那些極好的帶反斜杠的圓括號
    's///' 命令甚至比 '&' 更好,它允許我們在規則表達式中定義區域,然后可以在替換字符串中引用這些特定區域。作為示例,假設有一個包含以下文本的文件:

     foo bar oni eeny meeny miny larry curly moe jimmy the weasel 

    現在假設要編寫一個 sed 腳本,該腳本將把 "eeny meeny miny" 替換成 "Victor eeny-meeny Von miny" 等等。要這樣做,首先要編寫一個由空格分隔并與三個字符串匹配的規則表達式。

     '.* .* .*' 

    現在,將在其中每個感興趣的區域兩邊插入帶反斜杠的圓括號來定義區域:

     '(.*) (.*) (.*)' 

    除了要定義三個可在替換字符串中引用的邏輯區域以外,該規則表達式的工作原理將與第一個規則表達式相同。下面是最終腳本:

     $ sed -e 's/(.*) (.*) (.*)/Victor 1-2 Von 3/' myfile.txt 

    如您所見,通過輸入 'x'(其中,x 是從 1 開始的區域號)來引用每個由圓括號定界的區域。輸入如下:

     Victor foo-bar Von oni Victor eeny-meeny Von miny Victor larry-curly Von moe Victor jimmy-the Von weasel 

    隨著對 sed 越來越熟悉,您可以花最小力氣來進行相當強大的文本處理。您可能想如何使用熟悉的腳本語言來處理這種問題 -- 能用一行代碼輕易實現這樣的解決方案嗎?

    組合使用
    在開始創建更復雜的 sed 腳本時,需要有輸入多個命令的能力。有幾種方法這樣做。首先,可以在命令之間使用分號。例如,以下命令系列使用 '=' 命令和 'p' 命令,'=' 命令告訴 sed 打印行號,'p' 命令明確告訴 sed 打印該行(因為處于 '-n' 模式)。

     $ sed -n -e '=;p' myfile.txt 

    無論什么時候指定了兩個或更多命令,都按順序將每個命令應用到文件的每一行。在上例中,首先將 '=' 命令應用到第 1 行,然后應用 'p' 命令。接著,sed 繼續處理第 2 行,并重復該過程。雖然分號很方便,但是在某些場合下,它不能正常工作。另一種替換方法是使用兩個 -e 選項來指定兩個不同的命令:

     $ sed -n -e '=' -e 'p' myfile.txt 

    然而,在使用更為復雜的附加和插入命令時,甚至多個 '-e' 選項也不能幫我們的忙。對于復雜的多行腳本,最好的方法是將命令放入一個單獨的文件中。然后,用 -f 選項引用該腳本文件:

     $ sed -n -f mycommands.sed myfile.txt 

    這種方法雖然可能不太方便,但總是管用。

    一個地址的多個命令
    有時,可能要指定應用到一個地址的多個命令。這在執行許多 's///' 以變換源文件中的字和語法時特別方便。要對一個地址執行多個命令,可在文件中輸入 sed 命令,然后使用 '{ }' 字符將這些命令分組,如下所示:

     1,20{ s/[Ll]inux/GNU/Linux/g s/samba/Samba/g s/posix/POSIX/g } 

    上例將把三個替換命令應用到第 1 行到第 20 行(包括這兩行)。還可以使用規則表達式地址或者二者的組合:

     1,/^END/{         s/[Ll]inux/GNU/Linux/g         s/samba/Samba/g         s/posix/POSIX/g p } 

    該例將把 '{ }' 之間的所有命令應用到從第 1 行開始,到以字母 "END" 開始的行結束(如果在源文件中沒發現 "END",則到文件結束)的所有行。

    附加、插入和更改行
    既然在單獨的文件中編寫 sed 腳本,我們可以利用附加、插入和更改行命令。這些命令將在當前行之后插入一行,在當前行之前插入一行,或者替換模式空間中的當前行。它們也可以用來將多行插入到輸出。插入行命令用法如下:

     i This line will be inserted before each line 

    如果不為該命令指定地址,那么它將應用到每一行,并產生如下的輸出:

     This line will be inserted before each line line 1 here 
    This line will be inserted before each line line 2 here
    This line will be inserted before each line line 3 here
    This line will be inserted before each line line 4 here

    如果要在當前行之前插入多行,可以通過在前一行之后附加一個反斜杠來添加附加行,如下所示:

     i insert this line and this one and this one and, uh, this one too. 

    附加命令的用法與之類似,但是它將把一行或多行插入到模式空間中的當前行之后。其用法如下:

     a insert this line after each line.  Thanks! :) 

    另一方面,“更改行”命令將實際替換模式空間中的當前行,其用法如下:

     c You're history, original line! Muhahaha! 

    因為附加、插入和更改行命令需要在多行輸入,所以將把它們輸入到一個文本 sed 腳本中,然后通過使用 '-f' 選項告訴 sed 執行它們。使用其它方法將命令傳遞給 sed 會出現問題。

    下一篇
    在下一篇、也是本 sed 系列的最后一篇文章中,我將為您演示許多使用 sed 來完成不同類型任務的極佳實例。我將不僅為您顯示腳本做些什么,還顯示為什么那樣做。完成之后,您將掌握更多有關如何在不同項目中使用 sed 的極佳知識。到時候見!

    參考資料

    • 閱讀 developerWorks 上 Daniel 的其它 sed 文章:通用線程:sed 實例,第 1 部分第 3 部分。
    • 查看 Eric Pement 極佳的 sed faq。
    • 可以在 ftp.gnu.org 找到 sed 3.02 資源。
    • 將在 alpha.gnu.org 找到很好的新的 sed 3.02.80。
    • 另外,Eric Pement 還有一些方便的 sed 單行程序,任何有抱負的 sed 高手都應該看一下。
    • 如果想看好的老式書籍,O'Reilly 的 sed & awk, 2nd Edition 將是極佳選擇。
    • 可能想閱讀 7th edition UNIX's sed man page(大概 1978?。?。
    • 閱讀 Felix von Leitner 短小的 sed tutorial。
    • using regular expressions 中復習,發現和修改這個免費 dW 獨家教程文本中的模式。

    關于作者
    Daniel Robbins 居住在新墨西哥州的 Albuquerque。他是 Gentoo Technologies, Inc. 的總裁兼 CEO,Gentoo Linux(用于 PC 的高級 Linux)和 Portage 系統(Linux 的下一代端口系統)的創始人。他還是 Macmillan 書籍 Caldera OpenLinux Unleashed、SuSE Linux UnleashedSamba Unleashed 的作者。Daniel 自小學二年級起就與計算機結下不解之緣,那時他首先接觸的是 Logo 程序語言,并沉溺于 Pac-Man 游戲中。這也許就是他至今仍擔任 SONY Electronic Publishing/Psygnosis 的首席圖形設計師的原因所在。Daniel 喜歡與妻子 Mary 和新出生的女兒 Hadassah 一起共度時光??赏ㄟ^ drobbins@gentoo.org 與 Daniel Robbins 聯系。



    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>