Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

程式設計師聯盟發表於2019-02-20

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

— 作者 謝恩銘 轉載請註明出處

內容簡介


  1. 第三部分第一課:資料處理,慢條斯理
  2. 第三部分第二課預告:流、管道、重定向,三管齊下

資料處理,慢條斯理


哈哈,終於到了第三部分了。不知不覺兩個部分已經學完了,上一課是 Linux探索之旅 | 第二部分測試題

小編:可喜可賀,掌聲給自己!

此時讀者內心獨白:我想靜靜,也不要問我小編是誰。

好了好了,小編重回淡定。咳咳,看到今天的標題應該會對這一課的內容很有興趣吧,畢竟我們每天都在跟各種資料打交道。

Linux中的檔案裡也是各種資料,所以資料處理就顯得尤為重要。

之前的課中已經介紹過:大部分Linux的命令是基於Unix作業系統的模式,當然原始碼是重寫的。

因此,雖然Linux是1991年問世的,但是其很多設計理念和命令卻沿用了20世紀60年代的模式。

這樣的事實對我們學習Linux的人有個好處:不必每隔一段時間就學新東西,很多知識點可以沿用很久。例如現在近60歲的一個Unix的老工程師,操作Ubuntu等新近Linux發行版基本沒有什麼問題。

但也許你還是會問這個問題:為什麼過了這麼多年,好多Linux命令都沒變呢?

那是因為沒有必要變。因為大多數Linux命令都具有很基本的功能,而且它們在自己的崗位上敬忠職守,工作做得很棒。這些都是Linux系統的“基石”。

這一課我們將學習好多個基本的命令,這些命令用於提取、排序、篩選檔案中的各種資料。這一課也是很輕鬆的。

這些命令中,有些你以後幾乎每天都會用到,例如grep命令。

好了,閒話說完,該動手實踐了。

grep命令:篩選資料


grep是Globally search a Regular Expression and Print的縮寫,意思是《全域性搜尋一個正規表示式,並且列印》。

意思不太好理解吧?沒關係,也不需要太理解原意。

grep命令的功能簡單說來是在檔案中查詢關鍵字,並且顯示關鍵字所在的行。

grep命令極為強大,也是Linux中使用最多的命令之一。它的強大之處在於它不僅可以實現簡單的查詢,而且可以配合《正規表示式》來實現比較複雜的查詢。

至於什麼是正規表示式,大家有興趣可以去百度或Google,學習一下。這是程式設計師需要掌握的知識點之一。

正規表示式提供了搜尋文字的一種高階方式。我們不僅在Linux的命令列中用到正規表示式,而且在很多的文字編輯器裡也用到,在許多程式語言例如C++,Java,PHP等等也會用到。

首先,我們學習grep的簡單用法。之後我們再學習如何配合正規表示式來實現複雜的查詢。

grep的簡單用法


grep的使用方法有很多種。但我們一開始先學習最基本的用法:

grep text file複製程式碼

可以看到,上面就是grep命令的最基本用法。

text代表要搜尋的文字,file代表供搜尋的檔案。

我們用實際的例子來學習。比如我要在使用者的家目錄的 .bashrc 檔案中搜尋alias這個文字,而且顯示所有包含alias的行。

grep alias .bashrc複製程式碼

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

怎麼樣,grep命令很強大吧。如上圖所見,grep命令列出了.bashrc檔案中所有包含alias的行,並且在小編的終端中,以紅色標出了每一個alias。其實grep更像是一個過濾器,它可以篩選出我們要找的物件。

少年,不要激動,此物件非彼物件~

如果我們要用grep命令在一個檔案中查詢用空格隔開的文字,那麼就要加上雙引號,例如:

grep "Hello World" file2複製程式碼

-i引數:忽略大小寫


預設的情況下,grep命令是區分大小寫的,也就是說搜尋的文字將嚴格按照大小寫來搜尋。比如我搜尋的文字是text,那麼就不會搜出例如Text,tExt,TEXT等等文字。

但是我們可以給grep加上-i引數,使得grep可以忽略大小寫。i是英語ignore的縮寫,表示“忽略”。

例如:

grep -i alias .bashrc複製程式碼

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

可以看到,加了-i引數後,grep的搜尋結果就多了 #Alias definitions. 那一行,因為-i引數使得grep搜尋不區分大小寫。

-n引數:顯示行號


-n引數的作用很簡單,就是顯示搜尋到的文字所在的行號。n是英語number的縮寫,表示“數字,編號”。

grep -n alias .bashrc複製程式碼

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

-v引數:只顯示文字不在的行


-v引數很有意思,v是invert的縮寫,表示“顛倒,倒置”。-v引數的作用與正常grep的作用正好顛倒,就是隻顯示搜尋的文字不在的那些行。

grep -v alias .bashrc複製程式碼

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

可以看到,這次grep過濾出了.bashrc中所有不包含alias的行。

-r引數:在所有子目錄和子檔案中查詢


如果你不知道你要找的文字在哪個檔案裡,你可以用強大的-r引數。

r是英語recursive的縮寫,表示“遞迴”。

如果用了-r引數,那麼grep命令使用時的最後一個引數(grep text file這個模式中的file)需要換成directory,也就是必須是一個目錄。因為-r引數是讓grep命令能夠在指定目錄的所有子目錄和子檔案中查詢文字。

例如:

grep -r "Hello World" folder/複製程式碼

表示在folder這個目錄的所有子目錄和子檔案中查詢Hello World這個文字。當然了,以上例子中,folder後面的斜槓(/)不是必須的,這裡只是為了清楚表明folder是一個目錄。只要folder是一個目錄,Linux系統是不會搞錯的。

Linux中還有一個rgrep的命令,它的作用相當於grep -r

grep的高階用法:配合正規表示式


正規表示式使用單個字串來描述、匹配一系列符合某個句法規則的字串。

grep配合正規表示式就可以實現比較高階的搜尋了。

我們首先來看一眼以下的這個表格,表格中列出了最常用的一些正規表示式的字元以及其含義:

特殊字元 含義
. 匹配除 ”
” 之外的任何單個字元
^ 行首(匹配輸入字串的開始位置)
$ 行尾(匹配輸入字串的結束位置)
[] 在中括號中的任意一個字元
? 問號前面的元素出現零次或一次
* 星號前面的元素可能出現零次,一次或多次
+ 加號前面的元素必須出現一次以上(包含一次)
一根豎線 邏輯或
() 表示式的分組(表示範圍和優先度)

當然了,上表沒有列出所有的正規表示式的字元。大家可以上網搜尋,查詢完整的表格。

看了上表你可能會說:“我啥也看不懂啊…”。

這是正常的,正規表示式不是那麼容易入門的,但也不是太難。要把正規表示式講清楚,大概需要兩課的篇幅,我們這裡就不多做介紹了。

首先,為了讓grep命令知道我們要使用正規表示式,須要加上-E引數。例如:

grep -E Alias .bashrc複製程式碼

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

當然了,Linux也有一個命令egrep,其效果等同grep -E

不要懷疑,Alias也算是一個正規表示式,只不過沒有用到上面表格中的特殊符號而已。

到此為止,沒什麼新鮮的。我們用正規表示式只不過和之前的搜尋類似。接下來,我們才真的要用到正規表示式的特殊字元了。

首先來看這個例子:

grep -E ^alias .bashrc複製程式碼

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

這個例子中,我們用到了^這個特殊符號,上面的表格裡對於^已經做了說明:行首(匹配輸入字串的開始位置)。也就是說,^後面的字元須要出現在一行的開始。

因此,就搜出瞭如上圖中的三行,這三行都是包含alias,並且以alias開頭的。

再來舉幾個例子:

grep -E [Aa]lias .bashrc複製程式碼

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

上面的表格裡解釋了[]的作用,是將[]中的字元任取其一,因此[Aa]lias的意思就是既可以是Alias,又可以是alias。因此grep的搜尋結果把包含Alias和alias的行都列出來了。

再比如:

grep -E [0-4] .bashrc複製程式碼

用於搜尋包含0至4的任一數字的行。

grep -E [a-zA-Z] .bashrc複製程式碼

用於搜尋包含在a至z之間的任意字母或者A至Z之間的任意字母的行。

其他正規表示式還有很多例子。就不一一列舉了。

注意:
其實在Ubuntu這樣的Linux發行版中,grep如果要和正規表示式配合,不加-E引數也是可以的,正規表示式始終是啟用的。不過有的Unix發行版的系統可能不加-E引數就不能搜尋正規表示式,因此為了相容,我們一般教學的時候會說加上-E引數比較好。

sort命令:為檔案排序


sort是英語“排序”的意思。

sort命令用於對檔案的行進行排序。

為了演示,我們首先用文字編輯器(可以用nano)來建立一個檔案,名叫name.txt比如,然後在裡面寫入以下的行:

John
Paul
Luc
Matthew
Mark
jude
Daniel
Samuel
Job複製程式碼

隨便寫幾個英語常用名字就可以了。name是英語“名字”的意思。

然後,我們用sort命令來舉個例子:

sort name.txt複製程式碼

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

可以看到,sort命令將name.txt檔案中的行按照首字母的英文字典順序進行了排列。

可以看到,sort命令並不區分大小寫。

-o引數:將排序後的內容寫入新檔案


如果你開啟name.txt檔案,你會發現,經過了sort命令的“洗禮”,name.txt中的內容還是維持原來的順序。

單獨使用sort命令是不會真正改變檔案內容的,只是把排序結果顯示在終端上。

那我們要儲存排序結果到新的檔案怎麼辦呢?可以用-o引數。

sort -o name_sorted.txt name.txt複製程式碼

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

可以看到,name.txt經過sort命令排序之後的內容被儲存在了新的檔案name_sorted.txt中,而name.txt的內容是不變的。

-r引數:倒序排列


-r引數中的r是reverse的縮寫,是“相反,反面”的意思,與普通的僅用sort命令正好相反。

sort -r name.txt複製程式碼

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

-R引數:隨機排序


-R引數比較“無厘頭”,因為它會讓sort命令的排序變為隨機,就是任意排序,也許每次都不一樣。但在有些時候,還是很有用的。

sort -R name.txt複製程式碼

為了顯示每次排序都是隨機的,我們執行了兩次以上命令:

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

-n引數:對數字排序


對數字的排序有點特殊。預設地,僅用sort命令的時候,是不區分首字元是否是數字的,因此還是按照1-9的順序來排序。例如138會排在25前面,因為1排在2的前面。

那如果我們要sort命令識別整個數字,比如按照大小順序來說,25應該排在138前面,那該怎麼辦呢?

就可以請出我們的-n引數了。n是number的縮寫。是英語“數字”的意思。-n引數用於對數字進行排序,按從小到大排序。

為了演示,我們再用文字編輯器來建立一個檔案,就叫number.txt好了。

裡面隨便填一些數字,每行一個:

12
9
216
28
174
35
68複製程式碼

然後用sort不加-n引數和加上-n引數分別測試:

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

可以看到,不加-n引數時,sort就會把這些數字按首字元來排序,按照1-9的順序。

加上-n引數,就會把各行的數字看成一個整體,按照大小從小到大來排序了。

wc命令:檔案的統計


wc是word count的縮寫(不是“廁所”的意思,OK?),word是英語“單詞”的意思,count是英語“計算,統計,數數”的意思。

因此,wc命令貌似是用來統計單詞數目的,但其實wc的功能不僅止於此。wc命令還可以用來統計行數,字元數,位元組數等。

跟前面的命令一樣,wc命令的用法也是後接檔名。wc命令很有用,應該會成為你經常用到的命令之一。

如果不加選項引數,那麼wc命令的返回值有些特殊,有點晦澀難懂。

例如:

wc name.txt複製程式碼

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

可以看到返回值是

9 9 50 name.txt複製程式碼

最後的name.txt只是表明檔名,不需考慮。

那麼這三個數字:9,9,和50分別表示什麼呢?

這三個數字,按順序,分別表示:

  • 行數

  • 單詞數

  • 位元組數

因為我們之前建立name.txt時,每一行只有一個單詞(英語名字),所以這裡統計的行數和單詞數都是9。

-l引數:統計行數


為了只統計行數,我們可以加上-l引數。l是英語line的縮寫,表示“行”。

wc -l name.txt複製程式碼

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

-w引數:統計單詞數


w是英語word的縮寫,word是英語“單詞”的意思。因此-w引數用於統計單詞。

wc -w name.txt複製程式碼

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

-c引數:統計位元組數


不知道為什麼是c,因為byte或者octet(都可以表示《位元組》)的首字母都不是c啊。不管了。也許c是character(英語“字元”的意思)的縮寫吧。

wc -c name.txt複製程式碼

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

-m引數:統計字元數


不知道為什麼是m,因為character(英語“字元”)的首字母不是m啊。不管了。

wc -m name.txt複製程式碼

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

uniq命令:刪除檔案中的重複內容


有時候,檔案中包含重複的行。我們也許想要將重複的內容刪除。

這時,uniq命令就顯得很有用了。

uniq是英語unique的縮寫,表示“獨一無二的”。

為了演示,我們建立一個檔案repeat.txt(repeat是英語“重複”的意思),裡面寫入如下排序好的內容(因為uniq命令還是有點“呆”,因為它只能將連續的重複行變為一行):

Albert
China
France
France
France
John
Matthew
Matthew
patrick
Steve
Vincent複製程式碼

可以看到,有三個France連在一起,兩個Matthew連在一起。

我們用uniq命令來處理看看:

uniq repeat.txt複製程式碼

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

可以看到,三個連續的France只剩下一個了,兩個連續的Matthew也只剩一個了。

但是uniq命令並不會改變原檔案的內容,只會把處理後的內容顯示出來。如果想將處理後的內容儲存到一個新檔案中,可以使用如下的方法:

uniq repeat.txt unique.txt複製程式碼

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

-c引數:統計重複的行數


-c引數用於顯示重複的行數,如果是獨一無二的行,那麼數目就是1。

uniq -c repeat.txt複製程式碼

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

-d引數:只顯示重複行的值


-d引數只顯示重複的行的值。

uniq -d repeat.txt複製程式碼

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

cut命令:剪下檔案的一部分內容


cut是英語“剪下”的意思。大家平時肯定有剪下文字內容的經歷吧,一般剪下之後還要把剪下的內容貼上到某處。

cut命令用於對檔案的每一行進行剪下處理。

-c引數:根據字元數來剪下


比如,我們要name.txt的每一行只保留第2至第4個字元。可以這樣做:

cut -c 2-4 name.txt複製程式碼

Linux 探索之旅 | 第三部分第一課:資料處理,慢條斯理

總結


  1. grep命令應該算是最常用的在檔案中查詢關鍵字的工具了。

  2. grep命令可以通過正規表示式來查詢。一開始正規表示式會比較難記,但是很強大。我們可以呼叫egrep命令,其等價於grep -E。

  3. sort命令用於為檔案中的行按字母順序排序。使用-n引數可以按照數字順序排序。

  4. wc命令可以統計檔案中行數,單詞數或者位元組數。

  5. uniq命令可以用於刪除檔案中重複的內容。

  6. cut命令用於剪下檔案的一部分內容。

當然了,篇幅有限,我們不可能對每個命令的每個引數和每種用法都做詳細介紹,大家可以用man命令來查詢各個命令的手冊,自己學習。

第三部分第二課預告


今天的課就到這裡,一起加油吧!

下一課我們來學習:Linux探索之旅 | 第三部分第二課:流、管道、重定向,三管齊下,會比較難。


微信公眾號「程式設計師聯盟」ProgrammerLeague
我是謝恩銘,在巴黎奮鬥的軟體工程師。
我的簡介
我的經歷
熱愛生活,喜歡游泳,略懂烹飪。
人生格言:“向著標杆直跑”

相關文章