歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux基礎知識 >> Linux常用文本操作命令整理

Linux常用文本操作命令整理

日期:2017/3/2 17:15:43   编辑:Linux基礎知識

  簡單的總結一下常用的一些實用的Linux文本操作命令,包括wc(統計)、cut(切分)、sort(排序)、uniq(去重)、grep(查找)、sed(替換、插入、刪除)、awk(文本分析)。

1.統計命令——wc

  統計文件裡面有多少單詞,多少行,多少字符。

1.1 wc語法

# wc [-lwm]
選項與參數:
-l  :僅列出行;
-w  :僅列出多少字(英文單字);
-m  :多少字符;

1.2 wc使用

#wc /etc/passwd
40   45 1719 /etc/passwd

  40是行數,45是單詞數,1719是字節數

  wc的命令比較簡單使用,每個參數使用如下:

#wc -l /etc/passwd   #統計行數,在對記錄數時,很常用
/etc/passwd       #表示系統有40個賬戶
#wc -w /etc/passwd  #統計單詞出現次數
/etc/passwd
#wc -m /etc/passwd  #統計文件的字節數

2.切分命令——cut

2.1 cut語法

cut  [-bn] [file] 或 cut [-c] [file]  或  cut [-df] [file]

  使用說明
  cut 命令從文件的每一行剪切字節、字符和字段並將這些字節、字符和字段寫至標准輸出。
  如果不指定 File 參數,cut 命令將讀取標准輸入。必須指定 -b、-c 或 -f 標志之一。

  主要參數
  -b :
以字節為單位進行分割。這些字節位置將忽略多字節字符邊界,除非也指定了 -n 標志。
  -c :以字符為單位進行分割。
  -d :自定義分隔符,默認為制表符。
  -f :與-d一起使用,指定顯示哪個區域。
  -n :取消分割多字節字符。僅和 -b 標志一起使用。如果字符的最後一個字節落在由 -b 標志的 List 參數指示的<br />范圍之內,該字符將被寫出;否則,該字符將被排除。

2.2 cut一般以什麼為依據呢? 也就是說,我怎麼告訴cut我想定位到的剪切內容呢?

  cut命令主要是接受三個定位方法:

  第一,字節(bytes),用選項-b

  第二,字符(characters),用選項-c

  第三,域(fields),用選項-f

2.3 以“字節”為單位切分

  舉個例子吧,當你執行ps命令時,會輸出類似如下的內容:

$ who
rocrocket :0           2009-01-08 11:07
rocrocket pts/0        2009-01-08 11:23 (:0.0)
rocrocket pts/1        2009-01-08 14:15 (:0.0)

  如果我們想提取每一行的第3個字節,就這樣:

$ who|cut -b 3

  如果“字節”定位中,我想提取第3,第4、第5和第8個字節,怎麼辦?

  -b支持形如3-5的寫法,而且多個定位之間用逗號隔開就成了。看看例子吧:

$ who|cut -b 3-5,8
croe
croe
croe

  但有一點要注意,cut命令如果使用了-b選項,那麼執行此命令時,cut會先把-b後面所有的定位進行從小到大排序,然後再提取。因此這跟我們書寫的順序沒有關系。這個例子就可以說明這個問題:

$ who|cut -b 8,3-5
croe
croe
croe

  還有哪些類似“3-5”這樣的小技巧,列舉一下吧!

$ who
rocrocket :0           2009-01-08 11:07
rocrocket pts/0        2009-01-08 11:23 (:0.0)
rocrocket pts/1        2009-01-08 14:15 (:0.0)
$ who|cut -b -3
roc
roc
roc
$ who|cut -b 3-
crocket :0           2009-01-08 11:07
crocket pts/0        2009-01-08 11:23 (:0.0)
crocket pts/1        2009-01-08 14:15 (:0.0)

  想必你也看到了,-3表示從第一個字節到第三個字節,而3-表示從第三個字節到行尾。如果你細心,你可以看到這兩種情況下,都包括了第三個字節“c”。如果我執行who|cut -b -3,3-,你覺得會如何呢?答案是輸出整行,不會出現連續兩個重疊的c的。

$ who|cut -b -3,3-
rocrocket :0           2009-01-08 11:07
rocrocket pts/0        2009-01-08 11:23 (:0.0)
rocrocket pts/1        2009-01-08 14:15 (:0.0)

2.4 以"字符"為單位切分

  下面例子你似曾相識,提取第3,第4,第5和第8個字符:

$ who|cut -c 3-5,8
croe
croe
croe

  不過,看著怎麼和-b沒有什麼區別啊?莫非-b和-c作用一樣? 其實不然,看似相同,只是因為這個例子舉的不好,who輸出的都是單字節字符,所以用-b和-c沒有區別,如果你提取中文,區別就看出來了,來,看看中文提取的情況:

$ cat cut_ch.txt
星期一
星期二
星期三
星期四
$ cut -b 3 cut_ch.txt
?
?
?
?
$ cut -c 3 cut_ch.txt
一
二
三
四

  看到了吧,用-c則會以字符為單位,輸出正常;而-b只會傻傻的以字節(8位二進制位)來計算,輸出就是亂碼。既然提到了這個知識點,就再補充一句,如果你學有余力,就提高一下。當遇到多字節字符時,可以使用-n選項,-n用於告訴cut不要將多字節字符拆開。

$ cat cut_ch.txt |cut -b 2
?
?
?
?
$ cat cut_ch.txt |cut -nb 2
等價於
$ cat cut_ch.txt |cut -nb 1,2,3
星
星
星
星

2.5 以"域"為單位切分

  為什麼會有“域”的提取呢,因為剛才提到的-b和-c只能在固定格式的文檔中提取信息,而對於非固定格式的信息則束手無策。這時候“域”就派上用場了。如果你觀察過/etc/passwd文件,你會發現,它並不像who的輸出信息那樣具有固定格式,而是比較零散的排放。但是,冒號在這個文件的每一行中都起到了非常重要的作用,冒號用來隔開每一個項。

  我們很幸運,cut命令提供了這樣的提取方式,具體的說就是設置“間隔符”,再設置“提取第幾個域”,就OK了!

  以/etc/passwd的前五行內容為例:

$ cat /etc/passwd|head -n 5
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
$ cat /etc/passwd|head -n 5|cut -d : -f 1
root
bin
daemon
adm
lp

  看到了吧,用-d來設置間隔符為冒號,然後用-f來設置我要取的是第一個域,再按回車,所有的用戶名就都列出來了!呵呵 有成就感吧!

  當然,在設定-f時,也可以使用例如3-5或者4-類似的格式:

$ cat /etc/passwd|head -n 5|cut -d : -f 1,3-5
root:0:0:root
bin:1:1:bin
daemon:2:2:daemon
adm:3:4:adm
lp:4:7:lp
$ cat /etc/passwd|head -n 5|cut -d : -f 1,3-5,7
root:0:0:root:/bin/bash
bin:1:1:bin:/sbin/nologin
daemon:2:2:daemon:/sbin/nologin
adm:3:4:adm:/sbin/nologin
lp:4:7:lp:/sbin/nologin
$ cat /etc/passwd|head -n 5|cut -d : -f -2
root:x
bin:x
daemon:x
adm:x
lp:x

2.6 cut的弊端:

  如果遇到空格和制表符時,怎麼分辨呢?我覺得有點亂,怎麼辦?

  有時候制表符確實很難辨認,有一個方法可以看出一段空格到底是由若干個空格組成的還是由一個制表符組成的。

$ cat tab_space.txt
this is tab finish.
this is several space      finish.
$ sed -n l tab_space.txt
this is tab\tfinish.$
this is several space      finish.$

  看到了吧,如果是制表符(TAB),那麼會顯示為\t符號,如果是空格,就會原樣顯示。通過此方法即可以判斷制表符和空格了。注意,上面sed -n後面的字符是L的小寫字母哦,不要看錯。

  我應該在cut -d中用什麼符號來設定制表符或空格呢?

  其實cut的-d選項的默認間隔符就是制表符,所以當你就是要使用制表符的時候,完全就可以省略-d選項,而直接用-f來取域就可以了。如果你設定一個空格為間隔符,那麼就這樣:

$cat tab_space.txt |cut -d ' ' -f 1
this
this

  注意,兩個單引號之間可確實要有一個空格哦,不能偷懶。而且,你只能在-d後面設置一個空格,可不許設置多個空格,因為cut只允許間隔符是一個字符。

$ cat tab_space.txt |cut -d ' ' -f 1
cut: the delimiter must be a single character
Try `cut --help' for more information.

  此外,cut在處理多空格的時候會更麻煩,因為cut只擅長處理“以一個字符間隔”的文本內容。

3.排序命令——sort

3.1 sort語法:

  sort命令是幫我們依據不同的數據類型進行排序,其語法及常用參數格式:

sort [-bcfMnrtk][源文件][-o 輸出文件] 

  補充說明:sort可針對文本文件的內容,以行為單位來排序。

  參數:
  -b 忽略每行前面開始出的空格字符。
  -c 檢查文件是否已經按照順序排序。
  -f 排序時,忽略大小寫字母。
  -M 將前面3個字母依照月份的縮寫進行排序。
  -n 依照數值的大小排序。
  -o<輸出文件> 將排序後的結果存入指定的文件。
  -r 以相反的順序來排序。
  -t<分隔字符> 指定排序時所用的欄位分隔字符。
  -k 選擇以哪個區間進行排序。

3.2 sort的使用

  下面通過幾個例子來講述Sort的使用。

  (1)sort將文件的每一行作為一個單位,相互比較,比較原則是從首字符向後,依次按ASCII碼值進行比較,最後將他們按升序輸出。

$ cat seq.txt
banana
apple
pear
orange
$ sort seq.txt
apple
banana
orange
pear

  用戶可以保存排序後的文件內容,或把排序後的文件內容輸出至打印機。下例中用戶把排序後的文件內容保存到名為result的文件中。

$ Sort seq.txt > result

  (2)sort的-u選項

  它的作用很簡單,就是在輸出行中去除重復行。

$ cat seq.txt
banana
apple
pear
orange
pear
$ sort seq.txt
apple
banana
orange
pear
pear
$ sort -u seq.txt
apple
banana
orange
pear

  pear由於重復被-u選項無情的刪除了。

  (3)sort的-r選項

  sort默認的排序方式是升序,如果想改成降序,就加個-r就搞定了。

$ cat number.txt
1
3
5
2
4
$ sort number.txt
1
2
3
4
5
$ sort -r number.txt
5
4
3
2
1

  (4)sort的-o選項

  由於sort默認是把結果輸出到標准輸出,所以需要用重定向才能將結果寫入文件,形如sort filename > newfile。

  但是,如果你想把排序結果輸出到原文件中,用重定向可就不行了。

$ sort -r number.txt > number.txt
$ cat number.txt
$

  看,竟然將number清空了。就在這個時候,-o選項出現了,它成功的解決了這個問題,讓你放心的將結果寫入原文件。這或許也是-o比重定向的唯一優勢所在。

$ cat number.txt
1
3
5
2
4
$ sort -r number.txt -o number.txt
$ cat number.txt
5
4
3
2
1

  (5) sort的-n選項

  你有沒有遇到過10比2小的情況。我反正遇到過。出現這種情況是由於排序程序將這些數字按字符來排序了,排序程序會先比較1和2,顯然1小,所以就將10放在2前面喽。這也是sort的一貫作風。我們如果想改變這種現狀,就要使用-n選項,來告訴sort,“要以數值來排序”!

$ cat number.txt
1
10
19
11
2
5
$ sort number.txt
1
10
11
19
2
5
$ sort -n number.txt
1
2
5
10
11
19

  (6)sort的-t選項和-k選項

  如果有一個文件的內容是這樣:

$ cat facebook.txt
banana:30:5.5
apple:10:2.5
pear:90:2.3
orange:20:3.4

  這個文件有三列,列與列之間用冒號隔開了,第一列表示水果類型,第二列表示水果數量,第三列表示水果價格。那麼我想以水果數量來排序,也就是以第二列來排序,如何利用sort實現?幸好,sort提供了-t選項,後面可以設定間隔符。指定了間隔符之後,就可以用-k來指定列數了。

$ sort -n -k 2 -t ‘:’ facebook.txt
apple:10:2.5
orange:20:3.4
banana:30:5.5
pear:90:2.3

  (7) 其他的sort常用選項

  -f 會將小寫字母都轉換為大寫字母來進行比較,亦即忽略大小寫

  -c 會檢查文件是否已排好序,如果亂序,則輸出第一個亂序的行的相關信息,最後返回1

  -C 會檢查文件是否已排好序,如果亂序,不輸出內容,僅返回1

  -M 會以月份來排序,比如JAN小於FEB等等

  -b 會忽略每一行前面的所有空白部分,從第一個可見字符開始比較。

4.去重命令——uniq

4.1 uniq語法

  uniq命令可以去除排序過的文件中的重復行,因此uniq經常和sort合用。也就是說,為了使uniq起作用,所有的重復行必須是相鄰的。

# uniq [-icu]
選項與參數:
-i   :忽略大小寫字符的不同;
-c  :進行計數
-u  :只顯示唯一的行

4.2 uniq的使用

  testfile的內容如下:

# cat testfile
hello
world
friend
hello
world
hello

  直接刪除未經排序的文件,將會發現沒有任何行被刪除:

#uniq testfile  
hello
world
friend
hello
world
hello

  排序文件,默認是去重:

#cat words | sort |uniq
friend
hello
world

  排序之後刪除了重復行,同時在行首位置輸出該行重復的次數:

#sort testfile | uniq -c
1 friend
3 hello
2 world

  僅顯示存在重復的行,並在行首顯示該行重復的次數:

#sort testfile | uniq -dc
3 hello
2 world

  僅顯示不重復的行:

#sort testfile | uniq -u
friend 

5.查找命令——grep

5.1 grep語法

  Linux系統中grep命令是一種強大的文本搜索工具,它能使用正則表達式搜索文本,並把匹 配的行打印出來。grep全稱是Global Regular Expression Print,表示全局正則表達式版本,它的使用權限是所有用戶。

grep [options]

  主要參數
  [options]主要參數:
  -c:只輸出匹配行的計數。
  -I:不區分大 小寫(只適用於單字符)。
  -h:查詢多文件時不顯示文件名。
  -l:查詢多文件時只輸出包含匹配字符的文件名。
  -n:顯示匹配行及 行號。
  -s:不顯示不存在或無匹配文本的錯誤信息。
  -v:顯示不包含匹配文本的所有行。
  pattern正則表達式主要參數:
  \: 忽略正則表達式中特殊字符的原有含義。
  ^:匹配正則表達式的開始行。
  $: 匹配正則表達式的結束行。
  \<:從匹配正則表達 式的行開始。
  \>:到匹配正則表達式的行結束。
  [ ]:單個字符,如[A]即A符合要求 。
  [ - ]:范圍,如[A-Z],即A、B、C一直到Z都符合要求 。
  。:所有的單個字符。
  * :有字符,長度可以為0。

5.2 grep簡單使用

  顯示所有以d開頭的文件中包含 test的行:

$ grep 'test' d*

  顯示在aa,bb,cc文件中匹配test的行:

$ grep 'test' aa bb cc

  輸出匹配行的計數:

 grep -c "48" data.doc   #輸出文檔中含有48字符的行數

  顯示匹配行和行數:

grep -n "48" data.doc       #顯示所有匹配48的行和行號

  顯示非匹配的行:

grep -vn "48" data.doc      #輸出所有不包含48的行

  顯示非匹配的行:

grep -vn "48" data.doc      #輸出所有不包含48的行

  大小寫敏感:

grep -i "ab" data.doc       #輸出所有含有ab或Ab的字符串的行

5.3 grep正則表達式的應用 (注意:最好把正則表達式用單引號括起來)

grep '[239].' data.doc      #輸出所有含有以2,3或9開頭的,並且是兩個數字的行

  不匹配測試:

grep '^[^48]' data.doc      #不匹配行首是48的行

  使用擴展模式匹配:

grep -E '219|216' data.doc

  顯示所有包含每個字符串至少有5個連續小寫字符的字符串的行:

$ grep '[a-z]\{5\}' aa

  如果west被匹配,則es就被存儲到內存中,並標記為1,然後搜索任意個字符(.*),這些字符後面緊跟著 另外一個es(\1),找到就顯示該行。如果用egrep或grep -E,就不用”\”號進行轉義,直接寫成’w(es)t.*\1′就可以了:

$ grep 'w\(es\)t.*\1' aa

6.替換/查找/刪除命令——sed

6.1 sed語法

  sed是一個很好的文件處理工具,本身是一個管道命令,主要是以行為單位進行處理,可以將數據行進行替換、刪除、新增、選取等特定工作,下面先了解一下sed的用法。sed命令行格式為:

sed [-nefri] ‘command’ 輸入文本 

  常用選項:
   -n∶使用安靜(silent)模式。在一般 sed 的用法中,所有來自 STDIN的資料一般都會被列出到螢幕上。但如果加上 -n 參數後,則只有經過sed 特殊處理的那一行(或者動作)才會被列出來。
-e∶直接在指令列模式上進行 sed 的動作編輯;
-f∶直接將 sed 的動作寫在一個檔案內, -f filename 則可以執行 filename 內的sed 動作;
-r∶sed 的動作支援的是延伸型正規表示法的語法。(預設是基礎正規表示法語法)
-i∶直接修改讀取的檔案內容,而不是由螢幕輸出。

  常用命令:
a ∶新增, a 的後面可以接字串,而這些字串會在新的一行出現(目前的下一行)~
c ∶取代, c 的後面可以接字串,這些字串可以取代 n1,n2 之間的行!
d ∶刪除,因為是刪除啊,所以 d 後面通常不接任何咚咚;
   i ∶插入, i 的後面可以接字串,而這些字串會在新的一行出現(目前的上一行);
   p ∶列印,亦即將某個選擇的資料印出。通常 p 會與參數 sed -n 一起運作~
   s ∶取代,可以直接進行取代的工作哩!通常這個 s 的動作可以搭配正規表示法!例如 1,20s/old/new/g 就是啦!

6.2 sed的使用

  假設我們有一文件名為ab。

  刪除某行:

# sed '1d' ab              #刪除第一行 
# sed '$d' ab              #刪除最後一行
# sed '1,2d' ab           #刪除第一行到第二行
# sed '2,$d' ab           #刪除第二行到最後一行

  顯示某行:

# sed -n '1p' ab           #顯示第一行 
# sed -n '$p' ab           #顯示最後一行
# sed -n '1,2p' ab        #顯示第一行到第二行
# sed -n '2,$p' ab        #顯示第二行到最後一行

  使用模式進行查詢:

# sed -n '/ruby/p' ab    #查詢包括關鍵字ruby所在所有行
# sed -n '/\$/p' ab        #查詢包括關鍵字$所在所有行,使用反斜線\屏蔽特殊含義

  增加一行或多行字符串:

# cat ab
     Hello!
     ruby is me,welcome to my blog.
     end
# sed '1a drink tea' ab  #第一行後增加字符串"drink tea"
     Hello!
     drink tea
     ruby is me,welcome to my blog. 
     end
# sed '1,3a drink tea' ab #第一行到第三行後增加字符串"drink tea"
     Hello!
     drink tea
     ruby is me,welcome to my blog.
     drink tea
     end
     drink tea
# sed '1a drink tea\nor coffee' ab   #第一行後增加多行,使用換行符\n
     Hello!
     drink tea
     or coffee
     ruby is me,welcome to my blog.
     end

  代替一行或多行:

# sed '1c Hi' ab                #第一行代替為Hi
     Hi
     ruby is me,welcome to my blog.
     end
# sed '1,2c Hi' ab             #第一行到第二行代替為Hi
     Hi
     end

  替換一行中的某部分
  格式:sed 's/要替換的字符串/新的字符串/g' (要替換的字符串可以用正則表達式)

# sed -n '/ruby/p' ab | sed 's/ruby/bird/g'    #替換ruby為bird
# sed -n '/ruby/p' ab | sed 's/ruby//g'        #刪除ruby

   插入:

# sed -i '$a bye' ab         #在文件ab中最後一行直接輸入"bye"
# cat ab
  Hello!
  ruby is me,welcome to my blog.
  end
  bye

  刪除匹配行:

sed -i '/匹配字符串/d'  filename  (注:若匹配字符串是變量,則需要“”,而不是‘’。記得好像是)

  替換匹配行中的某個字符串:

sed -i '/匹配字符串/s/替換源字符串/替換目標字符串/g' filename

7.強大的文本分析命令——awk

7.1 awk語法  

  awk是一個強大的文本分析工具,相對於grep的查找,sed的編輯,awk在其對數據分析並生成報告時,顯得尤為強大。簡單來說awk就是把文件逐行的讀入,以空格為默認分隔符將每行切片,切開的部分再進行各種分析處理。

awk '{pattern + action}' {filenames}

  盡管操作可能會很復雜,但語法總是這樣,其中 pattern 表示 AWK 在數據中查找的內容,而 action 是在找到匹配內容時所執行的一系列命令。花括號({})不需要在程序中始終出現,但它們用於根據特定的模式對一系列指令進行分組。 pattern就是要表示的正則表達式,用斜槓括起來。

  awk語言的最基本功能是在文件或者字符串中基於指定規則浏覽和抽取信息,awk抽取信息後,才能進行其他文本操作。完整的awk腳本通常用來格式化文本文件中的信息。

  通常,awk是以文件的一行為處理單位的。awk每接收文件的一行,然後執行相應的命令,來處理文本。

7.2 awk入門

  假設last -n 5的輸出如下:

# last -n 5 # 僅取出前五行
root     pts/1   192.168.1.100  Tue Feb 10 11:21   still logged in
root     pts/1   192.168.1.100  Tue Feb 10 00:46 - 02:28  (01:41)
root     pts/1   192.168.1.100  Mon Feb  9 11:41 - 18:30  (06:48)
dmtsai   pts/1   192.168.1.100  Mon Feb  9 11:41 - 11:41  (00:00)
root     tty1                   Fri Sep  5 14:09 - 14:10  (00:01)

  如果只是顯示最近登錄的5個帳號:

#last -n 5 | awk  '{print $1}'
root
root
root
dmtsai
root

  awk工作流程是這樣的:讀入有'\n'換行符分割的一條記錄,然後將記錄按指定的域分隔符劃分域,填充域,$0則表示所有域,$1表示第一個域,$n表示第n個域。默認域分隔符是"空白鍵" 或 "[tab]鍵",所以$1表示登錄用戶,$3表示登錄用戶ip,以此類推。

  如果只是顯示/etc/passwd的賬戶:

#cat /etc/passwd |awk  -F ':'  '{print $1}'  
root
daemon
bin
sys

  這種是awk+action的示例,每行都會執行action{print $1}。

  -F指定域分隔符為':'。

  如果只是顯示/etc/passwd的賬戶和賬戶對應的shell,而賬戶與shell之間以tab鍵分割:

#cat /etc/passwd |awk  -F ':'  '{print $1"\t"$7}'
root    /bin/bash
daemon  /bin/sh
bin     /bin/sh
sys     /bin/sh

  如果只是顯示/etc/passwd的賬戶和賬戶對應的shell,而賬戶與shell之間以逗號分割,而且在所有行添加列名name,shell,在最後一行添加"blue,/bin/nosh":

#cat /etc/passwd |awk  -F ':'  'BEGIN {print "name,shell"}  {print $1","$7} END {print "blue,/bin/nosh"}'
name,shell
root,/bin/bash
daemon,/bin/sh
bin,/bin/sh
sys,/bin/sh
....
blue,/bin/nosh

  awk工作流程是這樣的:先執行BEGING,然後讀取文件,讀入有/n換行符分割的一條記錄,然後將記錄按指定的域分隔符劃分域,填充域,$0則表示所有域,$1表示第一個域,$n表示第n個域,隨後開始執行模式所對應的動作action。接著開始讀入第二條記錄······直到所有的記錄都讀完,最後執行END操作。

  搜索/etc/passwd有root關鍵字的所有行:

#awk -F: '/root/{print $7}' /etc/passwd             
/bin/bash

  這裡指定了action{print $7}。

7.3 awk進階

  7.3.1 內置變量

  awk有許多內置變量用來設置環境信息,這些變量可以被改變,下面給出了最常用的一些變量。

ARGC               命令行參數個數
ARGV               命令行參數排列
ENVIRON            支持隊列中系統環境變量的使用
FILENAME           awk浏覽的文件名
FNR                浏覽文件的記錄數
FS                 設置輸入域分隔符,等價於命令行 -F選項
NF                 浏覽記錄的域的個數
NR                 已讀的記錄數
OFS                輸出域分隔符
ORS                輸出記錄分隔符
RS                 控制記錄分隔符

  此外,$0變量是指整條記錄。$1表示當前行的第一個域,$2表示當前行的第二個域,......以此類推。

  統計/etc/passwd:文件名,每行的行號,每行的列數,對應的完整行內容:

#awk  -F ':'  '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd
filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash
filename:/etc/passwd,linenumber:2,columns:7,linecontent:daemon:x:1:1:daemon:/usr/sbin:/bin/sh
filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/bin/sh
filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/bin/sh

  使用printf替代print,可以讓代碼更加簡潔,易讀:

#awk  -F ':'  '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd
  7.3.2 變量和賦值

  除了awk的內置變量,awk還可以自定義變量。

  下面統計/etc/passwd的賬戶人數:

#awk '{count++;print $0;} END{print "user count is ", count}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
......
user count is  40

  count是自定義變量。之前的action{}裡都是只有一個print,其實print只是一個語句,而action{}可以有多個語句,以;號隔開。

  這裡沒有初始化count,雖然默認是0,但是妥當的做法還是初始化為0:

#awk 'BEGIN {count=0;print "[start]user count is ", count} {count=count+1;print $0;} END{print "[end]user count is ", count}' /etc/passwd
[start]user count is  0
root:x:0:0:root:/root:/bin/bash
...
[end]user count is  40
  7.3.3 條件語句

  awk中的條件語句是從C語言中借鑒來的,用法與C語言一致。

  統計某個文件夾下的文件占用的字節數,過濾4096大小的文件(一般都是文件夾):

#ls -l |awk 'BEGIN {size=0;print "[start]size is ", size} {if($5!=4096){size=size+$5;}} END{print "[end]size is ", size/1024/1024,"M"}' 
[end]size is  8.22339 M
  7.3.4 循環語句

  awk中的循環語句同樣借鑒於C語言,支持while、do/while、for、break、continue,這些關鍵字的語義和C語言中的語義完全相同。

  7.3.5 數組

  因為awk中數組的下標可以是數字和字母,數組的下標通常被稱為關鍵字(key)。值和關鍵字都存儲在內部的一張針對key/value應用hash的表格裡。由於hash不是順序存儲,因此在顯示數組內容時會發現,它們並不是按照你預料的順序顯示出來的。數組和變量一樣,都是在使用時自動創建的,awk也同樣會自動判斷其存儲的是數字還是字符串。一般而言,awk中的數組用來從記錄中收集信息,可以用於計算總和、統計單詞以及跟蹤模板被匹配的次數等等。

  顯示/etc/passwd的賬戶:

#awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd
0 root
1 daemon
2 bin
3 sys
4 sync
5 games
......

  這裡使用for循環遍歷數組。

Copyright © Linux教程網 All Rights Reserved