shell腳本學習十一(sed進階)

       之前學習瞭如何用sed編輯器的基本功能來處理數據流中的文本。sed編輯器的基礎命令能滿足大多數日常文本編輯需求。本篇文章是繼續學習sed編輯器提供的更多高級特性所做筆記。這些功能你未必會經常用到,但當需要時,知道這些功能的存在以及如何使用肯定是件好事

1.1  多行命令

       在使用sed編輯器的基礎命令時,你可能注意到了一個侷限。所有的sed編輯器命令都是針對單行數據執行操作的。在sed編輯器讀取數據流時,它會基於換行符的位置將數據分成行。sed編輯器根據定義好的腳本命令一次處理一行數據,然後移到下一行重複這個過程。  

        舉個例子,如果你正在數據中查找短語Linux System Administrators Group,它很有可能出現在兩行中,每行各包含其中一部分短語。如果用普通的sed編輯器命令來處理文本,就 不可能發現這種被分開的短語  

        sed編輯器包含了三個可用來處理多行文本的特殊命令來解決這個問題:

              N:將數據流中的下一行加進來創建一個多行組(multiline group)來處理。

              D:刪除多行組中的一行。

              P:打印多行組中的一行。 

   1.1.1  next命令

         ① 單行的next命令 

          小寫的n命令會告訴sed編輯器移動到數據流中的下一文本行,而不用重新回到命令的開始再執行一遍。記住,通常sed編輯器在移動到數據流中的下一文本行之前,會在當前行上執行完所有定義好的命令。單行next命令改變了這個流程。

          這聽起來可能有些複雜,沒錯,有時確實是。在這個例子中,你有個數據文件,共有5行內容,其中的兩行是空的。目標是刪除首行之後的空白行,而留下後一行之前的空白行。如果寫一個刪掉空白行的sed腳本,你會刪掉兩個空白行。

           

         由於要刪除的行是空行,沒有任何能夠標示這種行的文本可供查找。解決辦法是用n命令。 在這個例子中,腳本要查找含有單詞header的那一行。找到之後,n命令會讓sed編輯器移動到文本的下一行,也就是那個空行

          

          這時,sed編輯器會繼續執行命令列表,該命令列表使用d命令來刪除空白行。sed編輯器執行完命令腳本後,會從數據流中讀取下一行文本,並從頭開始執行命令腳本。因爲sed編輯器再也找不到包含單詞header的行了。所以也不會有其他行會被刪掉

        ② 合併文本行

          瞭解了單行版的next命令,現在來看看多行版的。單行next命令會將數據流中的下一文本行移動到sed編輯器的工作空間(稱爲模式空間)。多行版本的next命令(用大寫N)會將下一文本行添加到模式空間中已有的文本後

          這樣的作用是將數據流中的兩個文本行合併到同一個模式空間中。文本行仍然用換行符分隔,但sed編輯器現在會將兩行文本當成一行來處理

          

         sed編輯器腳本查找含有單詞first的那行文本。找到該行後,它會用N命令將下一行合併到那行,然後用替換命令s將換行符替換成空格。結果是,文本文件中的兩行在sed編輯器的輸出中成了一行。

        如果要在數據文件中查找一個可能會分散在兩行中的文本短語的話,這是個很實用的應用程序。這裏有個例子

       

       替換命令會在文本文件中查找特定的雙詞短語System Administrator。如果短語在一行中的話,事情很好處理,替換命令可以直接替換文本。但如果短語分散在兩行中的話,替換命令就沒法識別匹配的模式了。

       這時N命令就可以派上用場了

       

      注意,替換命令在System和Administrator之間用了通配符模式(.)來匹配空格和換行符這兩種情況。但當它匹配了換行符時,它就從字符串中刪掉了換行符,導致兩行合併成一行。這可能不是你想要的。     

     要解決這個問題,可以在sed編輯器腳本中用兩個替換命令:一個用來匹配短語出現在多行中的情況,一個用來匹配短語出現在單行中的情況

        

     第一個替換命令專門查找兩個單詞間的換行符,並將它放在了替換字符串中。

     第一個替換命令專門在兩個檢索詞之間尋找換行符,並將其納入替換字符串。這樣就允許你在新文本的同樣位置添加換行符了。 但這個腳本中仍有個小問題。這個腳本總是在執行sed編輯器命令前將下一行文本讀入到模式空間。當它到了後一行文本時,就沒有下一行可讀了,所以N命令會叫sed編輯器停止。如果要匹配的文本正好在數據流的後一行上,命令就不會發現要匹配的數據

     

     可以輕鬆地解決這個問題——將單行命令放到N命令 前面,並將多行命令放到N命令後面,像這樣: 

     

     現在,查找單行中短語的替換命令在數據流的後一行也能正常工作,多行替換命令則會負責短語出現在數據流中間的情況

  1.1.2  多行刪除命令

     前面的學習筆記章介紹了單行刪除命令(d)。sed編輯器用它來刪除模式空間中的當前行。但和N命令一 起使用時,使用單行刪除命令就要小心了

     

     刪除命令會在不同的行中查找單詞System和Administrator,然後在模式空間中將兩行都刪掉。 這未必是你想要的結果

     sed編輯器提供了多行刪除命令D,它只刪除模式空間中的第一行。該命令會刪除到換行符(含換行符)爲止的所有字符

    

    文本的第二行被N命令加到了模式空間,但仍然完好。如果需要刪掉目標數據字符串所在行的前一文本行,它能派得上用場。

    這裏有個例子,它會刪除數據流中出現在第一行前的空白行

    

    sed編輯器腳本會查找空白行,然後用N命令來將下一文本行添加到模式空間。如果新的模式 空間內容含有單詞header,則D命令會刪除模式空間中的第一行。如果不結合使用N命令和D命令, 就不可能在不刪除其他空白行的情況下只刪除第一個空白行

  1.1.3  多行打印命令

    多行打印命令只打印多行模式空間中的第一行。這包括模式空間中直到換行符爲止的所有字符。當你用-n選項來阻止腳本輸出時,它和顯示文本的單行p命令的用法大同小異

    

    當多行匹配出現時,P命令只會打印模式空間中的第一行。多行P命令的強大之處在和N命令及D命令組合使用時才能顯現出來。

    

    D命令的獨特之處在於強制sed編輯器返回到腳本的起始處,對同一模式空間中的內容重新執行這些命令(它不會從數據流中讀取新的文本行)。在命令腳本中加入N命令,你就能單步掃過整個模式空間,將多行一起匹配。

   接下來,使用P命令打印出第一行,然後用D命令刪除第一行並繞回到腳本的起始處。一旦返回,N命令會讀取下一行文本並重新開始這個過程。這個循環會一直繼續下去,直到數據流結束

 1.2  保持空間

    模式空間(pattern space)是一塊活躍的緩衝區,在sed編輯器執行命令時它會保存待檢查的 文本。但它並不是sed編輯器保存文本的唯一空間

    sed編輯器有另一塊稱作保持空間(hold space)的緩衝區域。在處理模式空間中的某些行時, 可以用保持空間來臨時保存一些行。有5條命令可用來操作保持空間

                                                     sed編輯器的保持空間命令

                               命 令                                                                           描述

                                  h                                                            將模式空間複製到保持空間

                                  H                                                           將模式空間附加到保持空間 

                                  g                                                            將保持空間複製到模式空間 

                                  G                                                           將保持空間附加到模式空間

                                  x                                                            交換模式空間和保持空間的內容 

       這些命令用來將文本從模式空間複製到保持空間。這可以清空模式空間來加載其他要處理的 字符串。

       通常,在使用h或H命令將字符串移動到保持空間後,終還要用g、G或x命令將保存的字符 串移回模式空間(否則,你就不用在一開始考慮保存它們了)。

       由於有兩個緩衝區域,弄明白哪行文本在哪個緩衝區域有時會比較麻煩。這裏有個簡短的例 子演示瞭如何用h和g命令來將數據在sed編輯器緩衝空間之間移動

       

      我們來一步一步看上面這個代碼例子:

      (1) sed腳本在地址中用正則表達式來過濾出含有單詞first的行;

      (2) 當含有單詞first的行出現時,h命令將該行放到保持空間;

      (3) p命令打印模式空間也就是第一個數據行的內容;

      (4) n命令提取數據流中的下一行(This is the second  line),並將它放到模式空間;

      (5) p命令打印模式空間的內容,現在是第二個數據行;

      (6) g命令將保持空間的內容(This is the first  line)放回模式空間,替換當前文本;

      (7) p命令打印模式空間的當前內容,現在變回第一個數據行了。

      通過使用保持空間來回移動文本行,你可以強制輸出中第一個數據行出現在第二個數據行後面。如果丟掉了第一個p命令,你可以以相反的順序輸出這兩行

      

      這是個有用的開端。你可以用這種方法來創建一個sed腳本將整個文件的文本行反轉!但要 那麼做的話,你需要了解sed編輯器的排除特性

  1.3  排除命令

      在前面學習初始sed這一部分時演示了了sed編輯器如何將命令應用到數據流中的每一個文本行或是由單個地址或地址 區間特別指定的多行。你也可以配置命令使其不要作用到數據流中的特定地址或地址區間。 

      感嘆號命令(!)用來排除(negate)命令,也就是讓原本會起作用的命令不起作用。下面的例子演示了這一特性。

      

      普通p命令只打印data2文件中包含單詞header的那行。加了感嘆號之後,情況就相反了:除 了包含單詞header那一行外,文件中其他所有的行都被打印出來了

      感嘆號在有些應用中用起來很方便。可以用感嘆號來解決sed編輯器無法處 理數據流中後一行文本的問題

      

     這個例子演示瞭如何配合使用感嘆號與N命令以及與美元符特殊地址。美元符表示數據流中的後一行文本,所以當sed編輯器到了後一行時,它沒有執行N命令,但它對所有其他行都執 行了這個命令

     使用這種方法,你可以反轉數據流中文本行的順序。要實現這個效果(先顯示後一行, 後顯示第一行),你得利用保持空間做一些特別的鋪墊工作。

    你得像這樣使用模式空間:

     (1) 在模式空間中放置一行;

     (2) 將模式空間中的行放到保持空間中;

     (3) 在模式空間中放入下一行;

     (4) 將保持空間附加到模式空間後;

     (5) 將模式空間中的所有內容都放到保持空間中;

     (6)重複執行第(3)~(5)步,直到所有行都反序放到了保持空間中;

     (7) 提取並打印行

     下圖詳細描述了整個過程

     

     在使用這種方法時,你不想在處理時打印行。這意味着要使用sed的-n命令行選項。下一步是決定如何將保持空間文本附加到模式空間文本後面。這可以用G命令完成。唯一的問題是你不想將保持空間附加到要處理的第一行文本後面。這可以用感嘆號命令輕鬆解決: 

     1!G 

     下一步就是將新的模式空間(含有已反轉的行)放到保持空間。這也非常簡單,只要用h命令就行。

     將模式空間中的整個數據流都反轉了之後,你要做的就是打印結果。當到達數據流中的後一行時,你就知道已經得到了模式空間的整個數據流。打印結果要用下面的命令: 
         $p 

     

     sed編輯器腳本的執行和預期的一樣。腳本輸出反轉了文本文件中原來的行。這展示了在sed 腳本中使用保持空間的強大之處。它提供了一種在腳本輸出中控制行順序的簡單辦法

    ---------------------------------------

    linux自帶的tac命令會倒序顯示一個文本文件,這個命令的名字很巧妙,它執行的正好是與cat命令相反的功能。

    ---------------------------------------

 1.4  改變流

      通常,sed編輯器會從腳本的頂部開始,一直執行到腳本的結尾(D命令是個例外,它會強制sed編輯器返回到腳本的頂部,而不讀取新的行)。sed編輯器提供了一個方法來改變命令腳本的執行流程,其結果與結構化編程類似

   1.4.1  分支

      sed編輯器提供了 一種方法,可以基於地址、地址模式或地址區間排除一整塊命令。這允許你只對數據流中的特定行執行一組命令。 分支(branch)命令b的格式如下:  

    [address] b [label] 

     address參數決定了哪些行的數據會觸發分支命令。label參數定義了要跳轉到的位置。如果沒有加label參數,跳轉命令會跳轉到腳本的結尾

     

     分支命令在數據流中的第2行和第3行處跳過了兩個替換命令。

    要是不想直接跳到腳本的結尾,可以爲分支命令定義一個要跳轉到的標籤。標籤以冒號開始, 多可以是7個字符長度。 
    

           :label2

    要指定標籤,將它加到b命令後即可。使用標籤允許你跳過地址匹配處的命令,但仍然執行腳本中的其他命令

     

     

     跳轉命令指定如果文本行中出現了first,程序應該跳到標籤爲jump1的腳本行。如果分支命令的模式沒有匹配,sed編輯器會繼續執行腳本中的命令,包括分支標籤後的命令(因此,所有的替換命令都會在不匹配分支模式的行上執行)。

     如果某行匹配了分支模式, sed編輯器就會跳轉到帶有分支標籤的那行。因此,只有後一個替換命令會執行。

     這個例子演示了跳轉到sed腳本後面的標籤上。也可以跳轉到腳本中靠前面的標籤上,這樣就達到了循環的效果

     

    腳本的每次迭代都會刪除文本中的第一個逗號,並打印字符串。這個腳本有個問題:它永遠不會結束。這就形成了一個無窮循環,不停地查找逗號,直到使用Ctrl+C組合鍵發送一個信號, 手動停止這個腳本。

    要防止這個問題,可以爲分支命令指定一個地址模式來查找。如果沒有模式,跳轉就應該結束

    

    現在分支命令只會在行中有逗號的情況下跳轉。在後一個逗號被刪除後,分支命令不會再 執行,腳本也就能正常停止了

 1.4.2  測試

    類似於分支命令,測試(test)命令(t)也可以用來改變sed編輯器腳本的執行流程。測試命令會根據替換命令的結果跳轉到某個標籤,而不是根據地址進行跳轉

    如果替換命令成功匹配並替換了一個模式,測試命令就會跳轉到指定的標籤。如果替換命令 未能匹配指定的模式,測試命令就不會跳轉

    測試命令使用與分支命令相同的格式:

    [address]t [label] 

    跟分支命令一樣,在沒有指定標籤的情況下,如果測試成功,sed會跳轉到腳本的結尾。

    測試命令提供了對數據流中的文本執行基本的if-then語句的一個低成本辦法。舉個例子, 如果已經做了一個替換,不需要再做另一個替換,那麼測試命令能幫上忙

     

    第一個替換命令會查找模式文本first。如果匹配了行中的模式,它就會替換文本,而且測試命令會跳過後面的替換命令。如果第一個替換命令未能匹配模式,第二個替換命令就會被執行。
    有了測試命令,你就能結束之前用分支命令形成的無限循環

    

    當無需替換時,測試命令不會跳轉而是繼續執行剩下的腳本

1.5  模式替代

    在使用通配符時,很 難知道到底哪些文本會匹配模式;舉個例子,假如你想在行中匹配的單詞兩邊上放上引號。如果你只是要匹配模式中的一個單詞,那就非常簡單

    $ echo "The cat sleeps in his hat." | sed 's/cat/"cat"/'

        The "cat" sleeps in his hat.

    $ 

     但如果你在模式中用通配符(.)來匹配多個單詞呢? 

      $ echo "The cat sleeps in his hat." | sed 's/.at/".at"/g'

         The ".at" sleeps in his ".at".

     $

     模式字符串用點號通配符來匹配at前面的一個字母。遺憾的是,用於替代的字符串無法匹配已匹配單詞中的通配符字符

  1.5.1 &符號

      sed編輯器提供了一個解決辦法。&符號可以用來代表替換命令中的匹配的模式。不管模式匹配的是什麼樣的文本,你都可以在替代模式中使用&符號來使用這段文本。這樣就可以操作模式 所匹配到的任何單詞了

      

      當模式匹配了單詞cat,"cat"就會出現在了替換後的單詞裏。當它匹配了單詞hat,"hat" 就出現在了替換後的單詞中

  1.5.2  替代單獨的單詞

      &符號會提取匹配替換命令中指定模式的整個字符串。有時你只想提取這個字符串的一部分。 當然可以這麼做,只是要稍微花點心思而已。

      sed編輯器用圓括號來定義替換模式中的子模式。你可以在替代模式中使用特殊字符來引用每個子模式。替代字符由反斜線和數字組成。數字表明子模式的位置。sed編輯器會給第一個子 模式分配字符\1,給第二個子模式分配字符\2,依此類推。

               --------------------------------------------------------------------------------------------------------------------------------------

          警告 當在替換命令中使用圓括號時,必須用轉義字符將它們標示爲分組字符而不是普通的圓括號。這跟轉義其他特殊字符正好相反

              --------------------------------------------------------------------------------------------------------------------------------------

      來看一個在sed編輯器腳本中使用這個特性的例子

      

     這個替換命令用一對圓括號將單詞System括起來,將其標示爲一個子模式。然後它在替代模式中使用\1來提取第一個匹配的子模式。這沒什麼特別的,但在處理通配符模式時卻特別有用。
    如果需要用一個單詞來替換一個短語,而這個單詞剛好是該短語的子字符串,但那個子字符串碰巧使用了通配符,這時使用子模式會方便很多

    

    在這種情況下,你不能用&符號,因爲它會替換整個匹配的模式。子模式提供了答案,允許你選擇將模式中的某部分作爲替代模式。

    當需要在兩個或多個子模式間插入文本時,這個特性尤其有用。這裏有個腳本,它使用子模式在大數字中插入逗號

    

   這個腳本將匹配模式分成了兩部分

   .*[0-9]

   [0-9]\{3\}

    這個模式會查找兩個子模式。第一個子模式是以數字結尾的任意長度的字符。第二個子模式是若干組三位數字。如果這個模式在文本中找到了,替代文本會在兩個子模式之間加一個逗號,每個子模式都會通過其位置來標示。 這個腳本使用測試命令來遍歷這個數字,直到放置好所有的逗號

1.6  在腳本中使用sed

   1.6.1  使用包裝腳本

      實現sed編輯器腳本的過程很煩瑣,尤其是腳本很長的話。可以將sed編 輯器命令放到shell包裝腳本(wrapper)中,不用每次使用時都重新鍵入整個腳本。包裝腳本充當着sed編輯器腳本和命令行之間的中間人角色

      在shell腳本中,可以將普通的shell變量及參數和sed編輯器腳本一起使用。這裏有個將命令行參數變量作爲sed腳本輸入的例子

       

       

       現在你能在任何文件上輕鬆使用這個sed編輯器腳本,再不用每次都在命令行上重新輸入了

    1.6.2  重定向sed的輸出

        默認情況下,sed編輯器會將腳本的結果輸出到STDOUT上。你可以在shell腳本中使用各種標 準方法對sed編輯器的輸出進行重定向。

        可以在腳本中用$()將sed編輯器命令的輸出重定向到一個變量中,以備後用。下面的例子使用sed腳本來向數值計算結果添加逗號

       

      

     在使用普通的階乘計算腳本後,腳本的結果會被作爲sed編輯器腳本的輸入,它會給結果加上逗號。然後echo語句使用這個值產生終結果

 1.7  創建sed實用工具

   1.7.1  加倍行間距

     首先,讓我們看一個向文本文件的行間插入空白行的簡單sed腳本

     這個技巧的關鍵在於保持空間的默認值。記住,G命令會簡單地將保持空間內容附加到模式空間內容後。當啓動sed編輯器時,保持空間只有一個空行。將它附加到已有行後面,你就在已有行後面創建了一個空白行

     ( 也就是說保持空間的默認值是一個空行,使用sed的G會將保持空間的值附加到模式空間已有行的後面

     你可能已經注意到了,這個腳本在數據流的後一行後面也加了一個空白行,使得文件的末尾也產生了一個空白行。如果你不想要這個空白行,可以用排除符號(!)和尾行符號($)來確保腳本不會將空白行加到數據流的後一行後面

     

     現在看起來好一些了。只要該行不是後一行,G命令就會附加保持空間內容。當sed編輯器 到了後一行時,它會跳過G命令

  1.7.2  對可能含有空白行的文件加倍行間距

     再進一步探索上面的例子:如果文本文件已經有一些空白行,但你想給所有行加倍行間距要 怎麼辦呢?如果用前面的腳本,有些區域會有太多的空白行,因爲每個已有的空白行也會被加倍

     

     現在,在原來空白行的位置有了三個空白行。這個問題的解決辦法是,首先刪除數據流中的所有空白行,然後用G命令在所有行後插入新的空白行。要刪除已有的空白行,需要將d命令和一 個匹配空白行的模式一起使用

     /^$/d

    這個模式使用了行首符號(^)和行尾符號($)。將這個模式加到腳本中會生成想要的結果

    

 1.7.3  給文件中的行編號

    如何用等號來顯示數據流中行的行號

    

    這可能有點難看,因爲行號是在數據流中實際行的上方。比較好的解決辦法是將行號和文本 放在同一行。

    你已經知道如何用N命令合併行,在sed腳本中使用這個命令應該不難。這個工具的技巧在於 不能將兩個命令放到同一個腳本中。

    在獲得了等號命令的輸出之後,你可以通過管道將輸出傳給另一個sed編輯器腳本,它會使用N命令來合併這兩行。還需要用替換命令將換行符更換成空格或製表符。最終的解決辦法看起來如下

    

    現在看起來好多了。在查看錯誤消息的行號時,這是一個很好用的小工具。

    有些bash shell命令也可以添加行號,但它們會另外加入一些東西(有可能是不需要的間隔)

    

  1.7.4  打印末尾行

      到目前爲止,已經學習瞭如何用p命令來打印數據流中所有的或者是匹配某個特定模式的行。 如果只需處理一個長輸出(比如日誌文件)中的末尾幾行,要怎麼辦呢? 

      美元符代表數據流中後一行,所以只顯示後一行很容易

      

      那麼,如何用美元符來顯示數據流末尾的若干行呢?答案是創建滾動窗口。

      滾動窗口是檢驗模式空間中文本行塊的常用方法,它使用N命令將這些塊合併起來。N命令將下一行文本附加到模式空間中已有文本行後面。一旦你在模式空間有了一個10行的文本塊,你可以用美元符來檢查你是否已經處於數據流的尾部。如果不在,就繼續向模式空間增加行,同時刪除原來的行(記住,D命令會刪除模式空間的第一行

      通過循環N命令和D命令,你在向模式空間的文本行塊增加新行的同時也刪除了舊行。分支命 令非常適合這個循環。要結束循環,只要識別出後一行並用q命令退出就可以了

     

    這個腳本會首先檢查這行是不是數據流中後一行。如果是,退出(quit)命令會停止循 環。N命令會將下一行附加到模式空間中當前行之後。如果當前行在第10行後面,11,$D命令會刪除模式空間中的第一行( 11,$D就是從第11行開始依次從第1行開始刪除,即第10行之後有幾行,就從首行開始刪除幾行 )。這就會在模式空間中創建出滑動窗口效果。因此,這個sed程序腳本只會顯示出data7.txt文件後10行

  1.7.5  刪除行

    另一個有用的sed編輯器工具是刪除數據流中不需要的空白行。刪除數據流中的所有空白行 很容易,但要選擇性地刪除空白行則需要一點創造力。這個小結的學習筆記將會給出一些簡短的sed編輯器腳本, 它們可以用來幫助刪除數據中不需要的空白行

    ① 刪除連續的空白行

    數據文件中出現多餘的空白行會非常讓人討厭。通常,數據文件中都會有空白行,但有時由 於數據行的缺失,會產生過多的空白行(就像之前加倍行間距例子中所見到的那樣)。

    刪除連續空白行的簡單辦法是用地址區間來檢查數據流。前面的學習筆記介紹瞭如何在地址中使用 區間,包括如何在地址區間中加入模式。sed編輯器會對所有匹配指定地址區間的行執行該命令。
    刪除連續空白行的關鍵在於創建包含一個非空白行和一個空白行的地址區間。如果sed編輯 器遇到了這個區間,它不會刪除行。但對於不匹配這個區間的行(兩個或更多的空白行),它會 刪除這些行。

   下面是完成這個操作的腳本:

    /./,/^$/!d 

   區間是/./到/^$/。區間的開始地址會匹配任何含有至少一個字符的行。區間的結束地址會 匹配一個空行。在這個區間內的行不會被刪除 

   

   無論文件的數據行之間出現了多少空白行,在輸出中只會在行間保留一個空白行

   ② 刪除開頭的空白行

    數據文件開頭有多個空白行時也很煩人。通常,在將數據從文本文件導入到數據庫時,空白行會產生一些空項,涉及這些數據的計算都得作廢。

    刪除數據流頂部的空白行不難。下面是完成這個功能的腳本

    /./,$!d 

    這個腳本用地址區間來決定哪些行要刪掉。這個區間從含有字符的行開始,一直到數據流結束。在這個區間內的任何行都不會從輸出中刪除。這意味着含有字符的第一行之前的任何行都會刪除

   

   測試文件在數據行之前有兩個空白行。這個腳本成功地刪除了開頭的兩個空白行,保留了數據中的空白行

   ③ 刪除結尾的空白行

   很遺憾,刪除結尾的空白行並不像刪除開頭的空白行那麼容易。就跟打印數據流的結尾一樣, 刪除數據流結尾的空白行也需要花點心思,利用循環來實現

   

  注意,在正常腳本的花括號裏還有花括號。這允許你在整個命令腳本 中將一些命令分組。該命令組會被應用在指定的地址模式上。地址模式能夠匹配只含有一個換行符的行。如果找到了這樣的行,而且還是後一行,刪除命令會刪掉它。如果不是後一行,N 命令會將下一行附加到它後面,分支命令會跳到循環起始位置重新開始

  

  這個腳本成功刪除了文本文件結尾的空白行

1.7.6  刪除HTML標籤

   現如今,從網站下載文本並將其保存或用作應用程序的數據並不罕見。但當你從網站下載文 本時,有時其中也包含了用於數據格式化的HTML標籤。如果你只是查看數據,這會是個問題。
   標準的HTML Web頁面包含一些不同類型的HTML標籤,標明瞭正確顯示頁面信息所需要的 格式化功能。這裏有個HTML文件的例子

   

   HTML標籤由小於號和大於號來識別。大多數HTML標籤都是成對出現的:一個起始標籤(比 如<b>用來加粗),以及另一個結束標籤(比如</b>用來結束加粗)。 

   但如果不夠小心的話,刪除HTML標籤可能會帶來問題。乍一看,你可能認爲刪除HTML標籤的辦法就是查找以小於號(<)開頭、大於號(>)結尾且其中有數據的文本字符串: 

   s/<.*>//g               s替換命令格式:s/匹配字段/替換字段/     (越學越迷……)

     

    注意,標題文本以及加粗和傾斜的文本都不見了。sed編輯器將這個腳本忠實地理解爲小於號和大於號之間的任何文本,且包括其他的小於號和大於號。每次文本出現在HTML標籤中(比如<b>first</b>),這個sed腳本都會刪掉整個文本。

    這個問題的解決辦法是讓sed編輯器忽略掉任何嵌入到原始標籤中的大於號。要這麼做的話, 你可以創建一個字符組來排除大於號。腳本改爲:

    s/<[^>]*>//g  

   [^>] 表示不包含>的所有字符  (  個人理解爲s不替換所有非">"符號的字段   )

    這個腳本現在能夠正常工作了,它會顯示你要在Web頁面HTML代碼裏看到的數據

    

    現在好一些了。要想看起來更清晰一些,可以加一條刪除命令來刪除多餘的空白行。 

    sed 's/<[^>]*>//g ; /^$/d' data11.txt 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章