日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

初识sed和gawk

發布時間:2023/12/20 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 初识sed和gawk 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

???????到目前為止, shell腳本最常見的一個用途就是處理文本文件。檢查日志文件、讀取配置文件、處理數據元素,shell腳本可以幫助我們將文本文件中各種數據的日常處理任務自動化。但僅靠shell腳本命令來處理文本文件的內容有點勉為其難。如果想在shell腳本中處理任何類型的數據,你得熟悉Linux中的sed和gawk工具。這兩個工具能夠極大簡化需要進行的數據處理任務。

一.文本處理
???????有時候,你會發現需要自動處理文本文件,可你又不想動用全副武裝的交互式文本編輯器。在這種情況下,有個能夠輕松實現自動格式化、插入、修改或刪除文本元素的簡單命令行編輯器就方便多了。
???????Linux系統提供了兩個常見的具備上述功能的工具。本節將會介紹Linux世界中最廣泛使用的兩個命令行編輯器:sed和gawk。

1.sed編輯器
???????sed編輯器被稱作流編輯器(stream editor),和普通的交互式文本編輯器恰好相反。在交互式文本編輯器中(比如vim),你可以用鍵盤命令來交互式地插入、刪除或替換數據中的文本。流編輯器則會在編輯器處理數據之前基于預先提供的一組規則來編輯數據流。
???????sed編輯器可以根據命令來處理數據流中的數據,這些命令要么從命令行中輸入,要么存儲在一個命令文本文件中。sed編輯器會執行下列操作。
???????(1) 一次從輸入中讀取一行數據。
???????(2) 根據所提供的編輯器命令匹配數據。
???????(3) 按照命令修改流中的數據。
???????(4) 將新的數據輸出到STDOUT。
???????在流編輯器將所有命令與一行數據匹配完畢后,它會讀取下一行數據并重復這個過程。在流編輯器處理完流中的所有數據行后,它就會終止。
???????由于命令是按順序逐行給出的,sed編輯器只需對數據流進行一遍處理就可以完成編輯操作。
這使得sed編輯器要比交互式編輯器快得多,你可以快速完成對數據的自動修改。
???????sed命令的格式如下。
???????sed options script file
???????選項允許你修改sed命令的行為,可以使用的選項已在表19-1中列出。

???????script參數指定了應用于流數據上的單個命令。如果需要用多個命令,要么使用-e選項在命令行中指定,要么使用-f選項在單獨的文件中指定。有大量的命令可用來處理數據。我們將會在本章后面介紹一些sed編輯器的基本命令,然后在第21章中會看到另外一些高級命令。

1)在命令行定義編輯器命令
???????默認情況下,sed編輯器會將指定的命令應用到STDIN輸入流上。這樣你可以直接將數據通過管道輸入sed編輯器處理。這里有個簡單的示例。

$ echo "This is a test" | sed 's/test/big test/' This is a big test $

???????這個例子在sed編輯器中使用了s命令。s命令會用斜線間指定的第二個文本字符串來替換第一個文本字符串模式。在本例中是big test替換了test。
???????在運行這個例子時,結果應該立即就會顯示出來。這就是使用sed編輯器的強大之處。你可以同時對數據做出多處修改,而所消耗的時間卻只夠一些交互式編輯器啟動而已。
???????當然,這個簡單的測試只是修改了一行數據。不過就算編輯整個文件,處理速度也相差無幾。

$ cat data1.txt The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. $ $ sed 's/dog/cat/' data1.txt The quick brown fox jumps over the lazy cat. The quick brown fox jumps over the lazy cat. The quick brown fox jumps over the lazy cat. The quick brown fox jumps over the lazy cat. $

???????sed命令幾乎瞬間就執行完并返回數據。在處理每行數據的同時,結果也顯示出來了。可以在sed編輯器處理完整個文件之前就開始觀察結果。
???????重要的是,要記住,sed編輯器并不會修改文本文件的數據。它只會將修改后的數據發送到STDOUT。如果你查看原來的文本文件,它仍然保留著原始數據。

$ cat data1.txt The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. $

2)在命令行使用多個編輯器命令
???????要在sed命令行上執行多個命令時,只要用-e選項就可以了。

$ sed -e 's/brown/green/; s/dog/cat/' data1.txt The quick green fox jumps over the lazy cat. The quick green fox jumps over the lazy cat. The quick green fox jumps over the lazy cat. The quick green fox jumps over the lazy cat. $

???????兩個命令都作用到文件中的每行數據上。命令之間必須用分號隔開,并且在命令末尾和分號之間不能有空格。
???????如果不想用分號,也可以用bash shell中的次提示符來分隔命令。只要輸入第一個單引號標示出sed程序腳本的起始(sed編輯器命令列表),bash會繼續提示你輸入更多命令,直到輸入了標示結束的單引號。

$ sed -e ' > s/brown/green/ > s/fox/elephant/ > s/dog/cat/' data1.txt The quick green elephant jumps over the lazy cat. The quick green elephant jumps over the lazy cat. The quick green elephant jumps over the lazy cat. The quick green elephant jumps over the lazy cat. $

???????必須記住,要在封尾單引號所在行結束命令。bash shell一旦發現了封尾的單引號,就會執行命令。開始后,sed命令就會將你指定的每條命令應用到文本文件中的每一行上。

3)從文件中讀取編輯器命令
???????最后,如果有大量要處理的sed命令,那么將它們放進一個單獨的文件中通常會更方便一些。可以在sed命令中用-f選項來指定文件。

$ cat script1.sed s/brown/green/ s/fox/elephant/ s/dog/cat/ $ $ sed -f script1.sed data1.txt The quick green elephant jumps over the lazy cat. The quick green elephant jumps over the lazy cat. The quick green elephant jumps over the lazy cat. The quick green elephant jumps over the lazy cat. $

???????在這種情況下,不用在每條命令后面放一個分號。sed編輯器知道每行都是一條單獨的命令。跟在命令行輸入命令一樣,sed編輯器會從指定文件中讀取命令,并將它們應用到數據文件中的每一行上。

2.gawk程序
???????雖然sed編輯器是非常方便自動修改文本文件的工具,但其也有自身的限制。通常你需要一個用來處理文件中的數據的更高級工具,它能提供一個類編程環境來修改和重新組織文件中的數據。這正是gawk能夠做到的。

???????gawk程序是Unix中的原始awk程序的GNU版本。gawk程序讓流編輯邁上了一個新的臺階,它提供了一種編程語言而不只是編輯器命令。在gawk編程語言中,你可以做下面的事情:
???????? 定義變量來保存數據;
???????? 使用算術和字符串操作符來處理數據;
???????? 使用結構化編程概念(比如if-then語句和循環)來為數據處理增加處理邏輯;
???????? 通過提取數據文件中的數據元素,將其重新排列或格式化,生成格式化報告。
???????gawk程序的報告生成能力通常用來從大文本文件中提取數據元素,并將它們格式化成可讀的報告。其中最完美的例子是格式化日志文件。在日志文件中找出錯誤行會很難,gawk程序可以讓你從日志文件中過濾出需要的數據元素,然后你可以將其格式化,使得重要的數據更易于閱讀。

1)gawk命令格式
???????gawk程序的基本格式如下:
???????gawk options program file
表19-2顯示了gawk程序的可用選項。

???????命令行選項提供了一個簡單的途徑來定制gawk程序中的功能。我們會在探索gawk時進一步
了解這些選項。
???????gawk的強大之處在于程序腳本。可以寫腳本來讀取文本行的數據,然后處理并顯示數據,創
建任何類型的輸出報告。

2)從命令行讀取程序腳本
???????gawk程序腳本用一對花括號來定義。你必須將腳本命令放到兩個花括號({})中。如果你錯誤地使用了圓括號來包含gawk腳本,就會得到一條類似于下面的錯誤提示。

$ gawk '(print "Hello World!"}' gawk: (print "Hello World!"} gawk: ^ syntax error

???????由于gawk命令行假定腳本是單個文本字符串,你還必須將腳本放到單引號中。下面的例子在命令行上指定了一個簡單的gawk程序腳本:

$ gawk '{print "Hello World!"}'

???????這個程序腳本定義了一個命令:print命令。這個命令名副其實:它會將文本打印到STDOUT。如果嘗試運行這個命令,你可能會有些失望,因為什么都不會發生。原因在于沒有在命令行上指定文件名,所以gawk程序會從STDIN接收數據。在運行這個程序時,它會一直等待從STDIN輸入的文本。
???????如果你輸入一行文本并按下回車鍵,gawk會對這行文本運行一遍程序腳本。跟sed編輯器一樣,gawk程序會針對數據流中的每行文本執行程序腳本。由于程序腳本被設為顯示一行固定的文本字符串,因此不管你在數據流中輸入什么文本,都會得到同樣的文本輸出。

$ gawk '{print "Hello World!"}' This is a test Hello World! hello Hello World! This is another test Hello World!

???????要終止這個gawk程序,你必須表明數據流已經結束了。bash shell提供了一個組合鍵來生成EOF(End-of-File)字符。Ctrl+D組合鍵會在bash中產生一個EOF字符。這個組合鍵能夠終止該gawk程序并返回到命令行界面提示符下。

3)使用數據字段變量
???????gawk的主要特性之一是其處理文本文件中數據的能力。它會自動給一行中的每個數據元素分配一個變量。默認情況下,gawk會將如下變量分配給它在文本行中發現的數據字段:
???????? $0代表整個文本行;
???????? $1代表文本行中的第1個數據字段;
???????? $2代表文本行中的第2個數據字段;
???????? $n代表文本行中的第n個數據字段。
???????在文本行中,每個數據字段都是通過字段分隔符劃分的。gawk在讀取一行文本時,會用預定義的字段分隔符劃分每個數據字段。gawk中默認的字段分隔符是任意的空白字符(例如空格或制表符)。
???????在下面的例子中,gawk程序讀取文本文件,只顯示第1個數據字段的值。

$ cat data2.txt One line of test text. Two lines of test text. Three lines of test text. $ $ gawk '{print $1}' data2.txt One Two Three $

???????該程序用$1字段變量來僅顯示每行文本的第1個數據字段。
???????如果你要讀取采用了其他字段分隔符的文件,可以用-F選項指定。

$ gawk -F: '{print $1}' /etc/passwd root bin daemon adm lp sync shutdown halt mail [...]

???????這個簡短的程序顯示了系統中密碼文件的第1個數據字段。由于/etc/passwd文件用冒號來分隔數字字段,因而如果要劃分開每個數據元素,則必須在gawk選項中將冒號指定為字段分隔符。

4) 在程序腳本中使用多個命令
???????如果一種編程語言只能執行一條命令,那么它不會有太大用處。gawk編程語言允許你將多條命令組合成一個正常的程序。要在命令行上的程序腳本中使用多條命令,只要在命令之間放個分號即可。

$ echo "My name is Rich" | gawk '{$4="Christine"; print $0}' My name is Christine $

???????第一條命令會給字段變量$4賦值。第二條命令會打印整個數據字段。注意, gawk程序在輸出中已經將原文本中的第四個數據字段替換成了新值。也可以用次提示符一次一行地輸入程序腳本命令。

$ gawk '{ > $4="Christine" > print $0}' My name is Rich My name is Christine $

???????在你用了表示起始的單引號后,bash shell會使用次提示符來提示你輸入更多數據。你可以每次在每行加一條命令,直到輸入了結尾的單引號。因為沒有在命令行中指定文件名,gawk程序會從STDIN中獲得數據。當運行這個程序的時候,它會等著讀取來自STDIN的文本。要退出程序,只需按下Ctrl+D組合鍵來表明數據結束。

5)從文件中讀取程序
???????跟sed編輯器一樣,gawk編輯器允許將程序存儲到文件中,然后再在命令行中引用。

$ cat script2.gawk {print $1 "'s home directory is " $6} $ $ gawk -F: -f script2.gawk /etc/passwd root's home directory is /root bin's home directory is /bin daemon's home directory is /sbin adm's home directory is /var/adm lp's home directory is /var/spool/lpd [...] Christine's home directory is /home/Christine Samantha's home directory is /home/Samantha Timothy's home directory is /home/Timothy $

???????script2.gawk程序腳本會再次使用print命令打印/etc/passwd文件的主目錄數據字段(字段變量$6),以及userid數據字段(字段變量$1)。
???????可以在程序文件中指定多條命令。要這么做的話,只要一條命令放一行即可,不需要用分號。

$ cat script3.gawk { text = "'s home directory is " print $1 text $6 } $ $ gawk -F: -f script3.gawk /etc/passwd root's home directory is /root bin's home directory is /bin daemon's home directory is /sbin adm's home directory is /var/adm lp's home directory is /var/spool/lpd [...] Christine's home directory is /home/Christine Samantha's home directory is /home/Samantha Timothy's home directory is /home/Timothy $

???????script3.gawk程序腳本定義了一個變量來保存print命令中用到的文本字符串。注意,gawk程序在引用變量值時并未像shell腳本一樣使用美元符。

6)在處理數據前運行腳本
???????gawk還允許指定程序腳本何時運行。默認情況下,gawk會從輸入中讀取一行文本,然后針對該行的數據執行程序腳本。有時可能需要在處理數據前運行腳本,比如為報告創建標題。BEGIN關鍵字就是用來做這個的。它會強制gawk在讀取數據前執行BEGIN關鍵字后指定的程序腳本。

$ gawk 'BEGIN {print "Hello World!"}' Hello World! $

???????這次print命令會在讀取數據前顯示文本。但在它顯示了文本后,它會快速退出,不等待任何數據。如果想使用正常的程序腳本中處理數據,必須用另一個腳本區域來定義程序。

$ cat data3.txt Line 1 Line 2 Line 3 $ $ gawk 'BEGIN {print "The data3 File Contents:"} > {print $0}' data3.txt The data3 File Contents: Line 1 Line 2 Line 3 $

???????在gawk執行了BEGIN腳本后,它會用第二段腳本來處理文件數據。這么做時要小心,兩段腳本仍然被認為是gawk命令行中的一個文本字符串。你需要相應地加上單引號。

7)在處理數據后運行腳本
???????與BEGIN關鍵字類似,END關鍵字允許你指定一個程序腳本,gawk會在讀完數據后執行它。

$ gawk 'BEGIN {print "The data3 File Contents:"} > {print $0} > END {print "End of File"}' data3.txt The data3 File Contents: Line 1 Line 2 Line 3 End of File $

???????當gawk程序打印完文件內容后,它會執行END腳本中的命令。這是在處理完所有正常數據后給報告添加頁腳的最佳方法。
???????可以將所有這些內容放到一起組成一個漂亮的小程序腳本文件,用它從一個簡單的數據文件中創建一份完整的報告。

$ cat script4.gawk BEGIN { print "The latest list of users and shells" print " UserID \t Shell" print "-------- \t -------" FS=":" } { print $1 " \t " $7 } END { print "This concludes the listing" } $

???????這個腳本用BEGIN腳本來為報告創建標題。它還定義了一個叫作FS的特殊變量。這是定義字段分隔符的另一種方法。這樣你就不用依靠腳本用戶在命令行選項中定義字段分隔符了。

???????下面是這個gawk程序腳本的輸出(有部分刪節)。

$ gawk -f script4.gawk /etc/passwd The latest list of users and shells UserID Shell -------- ------- root /bin/bash bin /sbin/nologin daemon /sbin/nologin [...] Christine /bin/bash mysql /bin/bash Samantha /bin/bash Timothy /bin/bash This concludes the listing $

???????與預想的一樣,BEGIN腳本創建了標題,程序腳本處理特定數據文件(/etc/passwd)中的信息,END腳本生成頁腳。
???????這個簡單的腳本讓你小試了一把gawk的強大威力。

二.sed編輯器基礎
???????成功使用sed編輯器的關鍵在于掌握其各式各樣的命令和格式,它們能夠幫助你定制文本編輯行為。本節將介紹一些可以集成到腳本中基本命令和功能。

1.更多的替換選項
???????你已經懂得了如何用s命令(substitute)來在行中替換文本。這個命令還有另外一些選項能讓事情變得更為簡單。

1)替換標記
???????關于替換命令如何替換字符串中所匹配的模式需要注意一點。看看下面這個例子中會出現什么情況。

$ cat data4.txt This is a test of the test script. This is the second test of the test script. $ $ sed 's/test/trial/' data4.txt This is a trial of the test script. This is the second trial of the test script. $

???????替換命令在替換多行中的文本時能正常工作,但默認情況下它只替換每行中出現的第一處。要讓替換命令能夠替換一行中不同地方出現的文本必須使用替換標記(substitution flag)。替換標記會在替換命令字符串之后設置。
???????s/pattern/replacement/flags
???????有4種可用的替換標記:
???????? 數字,表明新文本將替換第幾處模式匹配的地方;
???????? g,表明新文本將會替換所有匹配的文本;
???????? p,表明原先行的內容要打印出來;
???????? w file,將替換的結果寫到文件中。
???????在第一類替換中,可以指定sed編輯器用新文本替換第幾處模式匹配的地方。

$ sed 's/test/trial/2' data4.txt This is a test of the trial script. This is the second test of the trial script. $

???????將替換標記指定為2的結果就是:sed編輯器只替換每行中第二次出現的匹配模式。g替換標記使你能替換文本中匹配模式所匹配的每處地方。

$ sed 's/test/trial/g' data4.txt This is a trial of the trial script. This is the second trial of the trial script. $

???????p替換標記會打印與替換命令中指定的模式匹配的行。這通常會和sed的-n選項一起使用。

$ cat data5.txt This is a test line. This is a different line. $ $ sed -n 's/test/trial/p' data5.txt This is a trial line. $

???????-n選項將禁止sed編輯器輸出。但p替換標記會輸出修改過的行。將二者配合使用的效果就是只輸出被替換命令修改過的行。
???????w替換標記會產生同樣的輸出,不過會將輸出保存到指定文件中。

$ sed 's/test/trial/w test.txt' data5.txt This is a trial line. This is a different line. $ $ cat test.txt This is a trial line. $

???????sed編輯器的正常輸出是在STDOUT中,而只有那些包含匹配模式的行才會保存在指定的輸出文件中。

2) 替換字符
???????有時你會在文本字符串中遇到一些不太方便在替換模式中使用的字符。Linux中一個常見的例子就是正斜線(/)。
???????替換文件中的路徑名會比較麻煩。比如,如果想用C shell替換/etc/passwd文件中的bash shell,必須這么做:

$ sed 's/\/bin\/bash/\/bin\/csh/' /etc/passwd

???????由于正斜線通常用作字符串分隔符,因而如果它出現在了模式文本中的話,必須用反斜線來轉義。這通常會帶來一些困惑和錯誤。
???????要解決這個問題,sed編輯器允許選擇其他字符來作為替換命令中的字符串分隔符:

$ sed 's!/bin/bash!/bin/csh!' /etc/passwd

???????在這個例子中,感嘆號被用作字符串分隔符,這樣路徑名就更容易閱讀和理解了。

2.使用地址
???????默認情況下,在sed編輯器中使用的命令會作用于文本數據的所有行。如果只想將命令作用于特定行或某些行,則必須用行尋址(line addressing)。
???????在sed編輯器中有兩種形式的行尋址:
???????? 以數字形式表示行區間
???????? 用文本模式來過濾出行兩種形式都使用相同的格式來指定地址:
???????[address]command
也可以將特定地址的多個命令分組:
???????address {
???????command1
???????command2
???????command3
???????}
???????sed編輯器會將指定的每條命令作用到匹配指定地址的行上。本節將會演示如何在sed編輯器腳本中使用兩種尋址方法。

1) 數字方式的行尋址
???????當使用數字方式的行尋址時,可以用行在文本流中的行位置來引用。sed編輯器會將文本流中的第一行編號為1,然后繼續按順序為接下來的行分配行號。
???????在命令中指定的地址可以是單個行號,或是用起始行號、逗號以及結尾行號指定的一定區間范圍內的行。這里有個sed命令作用到指定行號的例子。

$ sed '2s/dog/cat/' data1.txt The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy cat The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog $

???????sed編輯器只修改地址指定的第二行的文本。這里有另一個例子,這次使用了行地址區間。

$ sed '2,3s/dog/cat/' data1.txt The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy cat The quick brown fox jumps over the lazy cat The quick brown fox jumps over the lazy dog $

???????如果想將命令作用到文本中從某行開始的所有行,可以用特殊地址——美元符。

$ sed '2,$s/dog/cat/' data1.txt The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy cat The quick brown fox jumps over the lazy cat The quick brown fox jumps over the lazy cat $

???????可能你并不知道文本中到底有多少行數據,因此美元符用起來通常很方便。

2)使用文本模式過濾器
???????另一種限制命令作用到哪些行上的方法會稍稍復雜一些。sed編輯器允許指定文本模式來過濾出命令要作用的行。格式如下:
???????attern/command
???????必須用正斜線將要指定的pattern封起來。sed編輯器會將該命令作用到包含指定文本模式的行上。
???????舉個例子,如果你想只修改用戶Samantha的默認shell,可以使用sed命令。

$ grep Samantha /etc/passwd Samantha:x:502:502::/home/Samantha:/bin/bash $ $ sed '/Samantha/s/bash/csh/' /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin [...] Christine:x:501:501:Christine B:/home/Christine:/bin/bash Samantha:x:502:502::/home/Samantha:/bin/csh Timothy:x:503:503::/home/Timothy:/bin/bash $

???????該命令只作用到匹配文本模式的行上。雖然使用固定文本模式能幫你過濾出特定的值,就跟上面這個用戶名的例子一樣,但其作用難免有限。sed編輯器在文本模式中采用了一種稱為正則表達式(regular expression)的特性來幫助你創建匹配效果更好的模式。
???????正則表達式允許創建高級文本模式匹配表達式來匹配各種數據。這些表達式結合了一系列通配符、特殊字符以及固定文本字符來生成能夠匹配幾乎任何形式文本的簡練模式。

3)命令組合
???????如果需要在單行上執行多條命令,可以用花括號將多條命令組合在一起。sed編輯器會處理地址行處列出的每條命令。

$ sed '2{ > s/fox/elephant/ > s/dog/cat/ > }' data1.txt The quick brown fox jumps over the lazy dog. The quick brown elephant jumps over the lazy cat. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. $

???????兩條命令都會作用到該地址上。當然,也可以在一組命令前指定一個地址區間。

$ sed '3,${ > s/brown/green/ > s/lazy/active/ > }' data1.txt The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick green fox jumps over the active dog. The quick green fox jumps over the active dog. $

???????sed編輯器會將所有命令作用到該地址區間內的所有行上。

3.刪除行
???????文本替換命令不是sed編輯器唯一的命令。如果需要刪除文本流中的特定行,可以用刪除命令。
???????刪除命令d名副其實,它會刪除匹配指定尋址模式的所有行。使用該命令時要特別小心,如果你忘記加入尋址模式的話,流中的所有文本行都會被刪除。

$ cat data1.txt The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog $ $ sed 'd' data1.txt $

???????當和指定地址一起使用時,刪除命令顯然能發揮出最大的功用。可以從數據流中刪除特定的文本行,通過行號指定:

$ cat data6.txt This is line number 1. This is line number 2. This is line number 3. This is line number 4. $ $ sed '3d' data6.txt This is line number 1. This is line number 2. This is line number 4. $

???????或者通過特定行區間指定:

$ sed '2,3d' data6.txt This is line number 1. This is line number 4. $

???????或者通過特殊的文件結尾字符:

$ sed '3,$d' data6.txt This is line number 1. This is line number 2. $

???????sed編輯器的模式匹配特性也適用于刪除命令。

$ sed '/number 1/d' data6.txt This is line number 2. This is line number 3. This is line number 4. $

???????sed編輯器會刪掉包含匹配指定模式的行。

???????也可以使用兩個文本模式來刪除某個區間內的行,但這么做時要小心。你指定的第一個模式會“打開”行刪除功能,第二個模式會“關閉”行刪除功能。sed編輯器會刪除兩個指定行之間的所有行(包括指定的行)。

$ sed '/1/,/3/d' data6.txt This is line number 4. $

???????除此之外,你要特別小心,因為只要sed編輯器在數據流中匹配到了開始模式,刪除功能就會打開。這可能會導致意外的結果。

$ cat data7.txt This is line number 1. This is line number 2. This is line number 3. This is line number 4. This is line number 1 again. This is text you want to keep. This is the last line in the file. $ $ sed '/1/,/3/d' data7.txt This is line number 4. $

???????第二個出現數字“1”的行再次觸發了刪除命令,因為沒有找到停止模式,所以就將數據流中的剩余行全部刪除了。當然,如果你指定了一個從未在文本中出現的停止模式,顯然會出現另外一個問題。

$ sed '/1/,/5/d' data7.txt $

???????因為刪除功能在匹配到第一個模式的時候打開了,但一直沒匹配到結束模式,所以整個數據流都被刪掉了。

4.插入和附加文本
???????如你所期望的,跟其他編輯器類似,sed編輯器允許向數據流插入和附加文本行。兩個操作的區別可能比較讓人費解:
???????? 插入(insert)命令(i)會在指定行前增加一個新行;
???????? 附加(append)命令(a)會在指定行后增加一個新行。
???????這兩條命令的費解之處在于它們的格式。它們不能在單個命令行上使用。你必須指定是要將行插入還是附加到另一行。格式如下:

sed '[address]command\ new line'

???????new line中的文本將會出現在sed編輯器輸出中你指定的位置。記住,當使用插入命令時,文本會出現在數據流文本的前面。

$ echo "Test Line 2" | sed 'i\Test Line 1' Test Line 1 Test Line 2 $

???????當使用附加命令時,文本會出現在數據流文本的后面。

$ echo "Test Line 2" | sed 'a\Test Line 1' Test Line 2 Test Line 1 $

???????在命令行界面提示符上使用sed編輯器時,你會看到次提示符來提醒輸入新的行數據。你必須在該行完成sed編輯器命令。一旦你輸入了結尾的單引號,bash shell就會執行該命令。

$ echo "Test Line 2" | sed 'i\ > Test Line 1' Test Line 1 Test Line 2 $

???????這樣能夠給數據流中的文本前面或后面添加文本,但如果要向數據流內部添加文本呢?
???????要向數據流行內部插入或附加數據,你必須用尋址來告訴sed編輯器你想讓數據出現在什么位置。可以在用這些命令時只指定一個行地址。可以匹配一個數字行號或文本模式,但不能用地址區間。這合乎邏輯,因為你只能將文本插入或附加到單個行的前面或后面,而不是行區間的前面或后面。
???????下面的例子是將一個新行插入到數據流第三行前。

$ sed '3i\ > This is an inserted line.' data6.txt This is line number 1. This is line number 2. This is an inserted line. This is line number 3. This is line number 4. $

???????下面的例子是將一個新行附加到數據流中第三行后。

$ sed '3a\ > This is an appended line.' data6.txt This is line number 1. This is line number 2. This is line number 3. This is an appended line. This is line number 4. $

???????它使用與插入命令相同的過程,只是將新文本行放到了指定的行號后面。如果你有一個多行數據流,想要將新行附加到數據流的末尾,只要用代表數據最后一行的美元符就可以了。

$ sed '$a\ > This is a new line of text.' data6.txt This is line number 1. This is line number 2. This is line number 3. This is line number 4. This is a new line of text. $

???????同樣的方法也適用于要在數據流起始位置增加一個新行。只要在第一行之前插入新行即可。
???????要插入或附加多行文本,就必須對要插入或附加的新文本中的每一行使用反斜線,直到最后一行。

$ sed '1i\ > This is one line of new text.\ > This is another line of new text.' data6.txt This is one line of new text. This is another line of new text. This is line number 1. This is line number 2. This is line number 3. This is line number 4. $

???????指定的兩行都會被添加到數據流中。

5.修改行
???????修改(change)命令允許修改數據流中整行文本的內容。它跟插入和附加命令的工作機制一樣,你必須在sed命令中單獨指定新行。

$ sed '3c\ > This is a changed line of text.' data6.txt This is line number 1. This is line number 2. This is a changed line of text. This is line number 4. $

???????在這個例子中,sed編輯器會修改第三行中的文本。也可以用文本模式來尋址。

$ sed '/number 3/c\ > This is a changed line of text.' data6.txt This is line number 1. This is line number 2. This is a changed line of text. This is line number 4. $

???????文本模式修改命令會修改它匹配的數據流中的任意文本行。

$ cat data8.txt This is line number 1. This is line number 2. This is line number 3. This is line number 4. This is line number 1 again. This is yet another line. This is the last line in the file. $ $ sed '/number 1/c\ > This is a changed line of text.' data8.txt This is a changed line of text. This is line number 2. This is line number 3. This is line number 4. This is a changed line of text. This is yet another line. This is the last line in the file. $

???????你可以在修改命令中使用地址區間,但結果未必如愿。

$ sed '2,3c\ > This is a new line of text.' data6.txt This is line number 1. This is a new line of text. This is line number 4. $

???????sed編輯器會用這一行文本來替換數據流中的兩行文本,而不是逐一修改這兩行文本。

6.轉換命令
???????轉換(transform)命令(y)是唯一可以處理單個字符的sed編輯器命令。轉換命令格式如下。
???????[address]y/inchars/outchars/
???????轉換命令會對inchars和outchars值進行一對一的映射。inchars中的第一個字符會被轉換為outchars中的第一個字符,第二個字符會被轉換成outchars中的第二個字符。這個映射過程會一直持續到處理完指定字符。如果inchars和outchars的長度不同,則sed編輯器會產生一條錯誤消息。
???????這里有個使用轉換命令的簡單例子。

$ sed 'y/123/789/' data8.txt This is line number 7. This is line number 8. This is line number 9. This is line number 4. This is line number 7 again. This is yet another line. This is the last line in the file. $

???????如你在輸出中看到的,inchars模式中指定字符的每個實例都會被替換成outchars模式中相同位置的那個字符。
???????轉換命令是一個全局命令,也就是說,它會文本行中找到的所有指定字符自動進行轉換,而不會考慮它們出現的位置。

$ echo "This 1 is a test of 1 try." | sed 'y/123/456/' This 4 is a test of 4 try. $

???????sed編輯器轉換了在文本行中匹配到的字符1的兩個實例。你無法限定只轉換在特定地方出現的字符。

7.回顧打印
???????介紹了如何使用p標記和替換命令顯示sed編輯器修改過的行。另外有3個命令也能用來打印數據流中的信息:
???????? p命令用來打印文本行;
???????? 等號(=)命令用來打印行號;
???????? l(小寫的L)命令用來列出行。
???????接下來的幾節將會介紹這3個sed編輯器的打印命令。

1)打印行
跟替換命令中的p標記類似,p命令可以打印sed編輯器輸出中的一行。如果只用這個命令,也沒什么特別的。

$ echo "this is a test" | sed 'p' this is a test this is a test $

???????它所做的就是打印已有的數據文本。打印命令最常見的用法是打印包含匹配文本模式的行。

$ cat data6.txt This is line number 1. This is line number 2. This is line number 3. This is line number 4. $ $ sed -n '/number 3/p' data6.txt This is line number 3. $

???????在命令行上用-n選項,你可以禁止輸出其他行,只打印包含匹配文本模式的行。也可以用它來快速打印數據流中的某些行。

$ sed -n '2,3p' data6.txt This is line number 2. This is line number 3. $

???????如果需要在修改之前查看行,也可以使用打印命令,比如與替換或修改命令一起使用。可以創建一個腳本在修改行之前顯示該行。

$ sed -n '/3/{ > p > s/line/test/p > }' data6.txt This is line number 3. This is test number 3. $

???????sed編輯器命令會查找包含數字3的行,然后執行兩條命令。首先,腳本用p命令來打印出原始行;然后它用s命令替換文本,并用p標記打印出替換結果。輸出同時顯示了原來的行文本和新的行文本。

2)打印行號
???????等號命令會打印行在數據流中的當前行號。行號由數據流中的換行符決定。每次數據流中出現一個換行符,sed編輯器會認為一行文本結束了。

$ cat data1.txt The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. $ $ sed '=' data1.txt 1 The quick brown fox jumps over the lazy dog. 2 The quick brown fox jumps over the lazy dog. 3 The quick brown fox jumps over the lazy dog. 4 The quick brown fox jumps over the lazy dog. $

???????sed編輯器在實際的文本行出現前打印了行號。如果你要在數據流中查找特定文本模式的話,等號命令用起來非常方便。

$ sed -n '/number 4/{ > = > p > }' data6.txt 4 This is line number 4. $

???????利用-n選項,你就能讓sed編輯器只顯示包含匹配文本模式的行的行號和文本。

3)列出行
???????列出(list)命令(l)可以打印數據流中的文本和不可打印的ASCII字符。任何不可打印字符要么在其八進制值前加一個反斜線,要么使用標準C風格的命名法(用于常見的不可打印字符),比如\t,來代表制表符。

$ cat data9.txt This line contains tabs. $ $ sed -n 'l' data9.txt This\tline\tcontains\ttabs.$ $

???????制表符的位置使用\t來顯示。行尾的美元符表示換行符。如果數據流包含了轉義字符,列出命令會在必要時候用八進制碼來顯示。

$ cat data10.txt This line contains an escape character. $ $ sed -n 'l' data10.txt This line contains an escape character. \a$ $

???????data10.txt文本文件包含了一個轉義控制碼來產生鈴聲。當用cat命令來顯示文本文件時,你看不到轉義控制碼,只能聽到聲音(如果你的音箱打開的話)。但是,利用列出命令,你就能顯示出所使用的轉義控制碼。

8.使用sed處理文件
???????替換命令包含一些可以用于文件的標記。還有一些sed編輯器命令也可以實現同樣的目標,不需要非得替換文本。
1)寫入文件
???????w命令用來向文件寫入行。該命令的格式如下:
???????[address]w filename
???????filename可以使用相對路徑或絕對路徑,但不管是哪種,運行sed編輯器的用戶都必須有文件的寫權限。地址可以是sed中支持的任意類型的尋址方式,例如單個行號、文本模式、行區間或文本模式。
???????下面的例子是將數據流中的前兩行打印到一個文本文件中。

$ sed '1,2w test.txt' data6.txt This is line number 1. This is line number 2. This is line number 3. This is line number 4. $ $ cat test.txt This is line number 1. This is line number 2. $

???????當然,如果你不想讓行顯示到STDOUT上,你可以用sed命令的-n選項。
???????如果要根據一些公用的文本值從主文件中創建一份數據文件,比如下面的郵件列表中的,那么w命令會非常好用。

$ cat data11.txt Blum, R Browncoat McGuiness, A Alliance Bresnahan, C Browncoat Harken, C Alliance $ $ sed -n '/Browncoat/w Browncoats.txt' data11.txt $ $ cat Browncoats.txt Blum, R Browncoat Bresnahan, C Browncoat $

???????sed編輯器會只將包含文本模式的數據行寫入目標文件。

  • 從文件讀取數據
    ???????你已經了解了如何在sed命令行上向數據流中插入或附加文本。讀取(read)命令(r)允許你將一個獨立文件中的數據插入到數據流中。
    ???????讀取命令的格式如下:
    ???????[address]r filename
    ???????filename參數指定了數據文件的絕對路徑或相對路徑。你在讀取命令中使用地址區間,只能指定單獨一個行號或文本模式地址。sed編輯器會將文件中的文本插入到指定地址后。
  • $ cat data12.txt This is an added line. This is the second added line. $ $ sed '3r data12.txt' data6.txt This is line number 1. This is line number 2. This is line number 3. This is an added line. This is the second added line. This is line number 4. $

    ???????sed編輯器會將數據文件中的所有文本行都插入到數據流中。同樣的方法在使用文本模式地址時也適用。

    $ sed '/number 2/r data12.txt' data6.txt This is line number 1. This is line number 2. This is an added line. This is the second added line. This is line number 3. This is line number 4. $

    ???????如果你要在數據流的末尾添加文本,只需用美元符地址符就行了。

    $ sed '$r data12.txt' data6.txt This is line number 1. This is line number 2. This is line number 3. This is line number 4. This is an added line. This is the second added line. $

    ???????讀取命令的另一個很酷的用法是和刪除命令配合使用:利用另一個文件中的數據來替換文件中的占位文本。舉例來說,假定你有一份套用信件保存在文本文件中:

    $ cat notice.std Would the following people: LIST please report to the ship's captain. $

    ???????套用信件將通用占位文本LIST放在人物名單的位置。要在占位文本后插入名單,只需讀取命令就行了。但這樣的話,占位文本仍然會留在輸出中。要刪除占位文本的話,你可以用刪除命令。結果如下:

    $ sed '/LIST/{ > r data11.txt > d > }' notice.std Would the following people: Blum, R Browncoat McGuiness, A Alliance Bresnahan, C Browncoat Harken, C Alliance please report to the ship's captain. $

    現在占位文本已經被替換成了數據文件中的名單。

    總結

    以上是生活随笔為你收集整理的初识sed和gawk的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。