1. 程式人生 > >Linux文字處理三劍客awk、sed、grep入門

Linux文字處理三劍客awk、sed、grep入門

AWK命令簡介

AWK是一門解釋型的程式語言,它的名字來源於它的三位作者的姓氏:Alfred Aho,Peter Weinberger和Brian Kernighan。AWK能夠應用於廣泛的計算和資料處理任務。所有的GNU/Linux發行版都自帶GAWK,即GNU AWK,是AWK的擴充套件並且與AWK完全相容。Awk也是一種模式匹配語言。它通過正則表示式匹配資料,然後就可以對這些匹配的資料進行相應的操作了。

一、基本格式:

AWK命令兩種格式:

第一種格式,awk從input-file中獲取輸入流,然後執行單引號內的程式。

awk [options] 'program' input-file

例1:awk ‘{print $2, $4}’ myfile  #輸出每一行的第二個和第四個單詞

例2:awk ‘length<60 {print}’ myfile #將長度小於60個字元的所有行全部輸出

第二種格式則是從檔案program-file中獲取將要執行的程式。

awk -f program-file input-file  # –f 選項,表示執行檔案中的命令

program-file的內容:

#!/usr/bin/awk –f

BEGIN{print "Output start!"};

{print};

END{print "Output done!"};

以上兩種格式可以統一表示為:

awk [ -F re] [parameter...] ['prog'] [-f progfile] in_file

引數說明:

-F re:    允許awk更改其欄位分隔符(預設為空格,可以設定為其他,如冒號)。

Parameter:該引數幫助為不同的變數賦值。

'prog':    awk的程式語句段,這個語句段必須用單括號,以防被shell解釋。這個程式語句段的標準形式為:

'pattern {action}'

其中pattern引數可以是egrep正則表示式中的任何一個。action引數總是被大括號包圍,它由一系列awk語句組成,可以省略pattern和 action之一,但不能兩者同時省略,當省略pattern時沒有樣式匹配,表示對所有行(記錄)均執行操作,省略action時執行預設的操作——在標準輸出上顯示。其中例2中的“length<60”就是pattern,其中 pattern 表示 AWK 在資料中查詢的內容,理解為條件。print就是action,而 action 是在找到匹配內容時所執行的一系列。命令意思就是滿足什麼條件(pattern)執行什麼動作(action)。

AWK 包含兩種特殊的模式:BEGIN 和 END。BEGIN 模式指定了處理文字之前需要執行的操作,END 模式指定了處理完所有行之後所需要執行的操作。

-f progfile:允許awk呼叫並執行progfile指定有程式檔案。progfile是一個文字檔案,他必須符合awk的語法。

in_file:awk的輸入檔案,awk允許對多個輸入檔案進行處理。值得注意的是awk不修改輸入檔案。如果未指定輸入檔案,awk將接受標準輸入,並將結果顯示在標準輸出上。awk支援輸入輸出重定向。

二、內建變數:

awk中定義了很多內建變數,這些內建的變數可以在awk程式中引用或修改。

FNR:當前處理的記錄號。

FS :欄位的分隔符,預設為空格。

IGNORECASE:如果該變數設定為非0值,在進行字串匹配時忽略大小寫。

NF:當前記錄中的欄位個數。

NR:已經讀出的記錄數。

OFMT:數字的輸出格式。

OFS:  輸出的欄位分隔符,預設為空格。

ORS:  輸出的記錄分隔符,預設為新行。

RS:   輸入記錄的分隔符,預設為新行。

等等

例3:

顯示文字檔案myfile中第七行到第十五行中以字元%分隔的第一欄位,第三欄位和第七欄位:

awk -F % 'NR>=7,NR<=15 {print $1 $3 $7}' myfile

三、內建函式

awk定義並支援了一系列的內建函式,使得awk提供的功能更為完善和強大,例如,awk使用了一系列的字串處理內建函式。

gsub(r,s) : 在整個$0中用s代替r

gsub(r,s,t) :在整個t中用s替代r

index(s,t) :返回s中字串t的第一位置

length(s) : 返回s長度

match(s,r) :測試s是否包含匹配r的字串

split(s,a,fs) :在fs上將s分成序列a

sprint(fmt,exp) :返回經fmt格式化後的exp

sub(r,s) :用$0中最左邊最長的子串代替s

substr(s,p) :返回字串s中從p開始的字尾部分

substr(s,p,n) :返回字串s中從p開始長度為n的字尾部分

例4:

該命令列將顯示文字myfile中所有超過80個字元的行號,在這裡,用0表示整個記錄(行)。

awk 'length($0)>80 {print NR}' myfile

sed命令簡介

sed命令是一個面向字元流的非互動式編輯器,也就是說sed不允許使用者與它進行互動操作。sed是按行來處理文字內容的。在shell中,使用sed來批量修改文字內容是非常方便的。

sed的命令格式:

sed [option] command file

1.[option]:

-n :使用安靜(silent)模式。在一般 sed 的用法中,所有來自stdin的資料一般都會被列出到終端上。加上 -n 引數後,則只有經過sed 特殊處理的那一行(或者動作)才會被列出來。

-e :直接在命令列模式上進行 sed 的動作編輯;

-f :直接將 sed 的動作寫在一個檔案內, -f filename 則可以執行 filename 內的 sed 動作;

-r :sed 的動作支援的是延伸型正規表示法的語法。(預設是基礎正規表示法語法)

-i :直接修改讀取的檔案內容,而不是輸出到終端。

2.Command:

a :新增行, a 的後面可以是字串,而這些字串會在新的一行出現(目前的下一行);

c :取代行, c 的後面可以接字串,這些字串可以取代 n1,n2 之間的行;

d :刪除行,因為是刪除,所以 d 後面通常不接任何引數,直接刪除地址表示的行;

i :插入行, i 的後面可以接字串,而這些字串會在新的一行出現(目前的上一行);

p :列印,亦即將某個選擇的資料印出。通常 p 會與引數 sed -n 一起執行;

s :替換,可以直接進行替換的工作,通常這個 s 的動作可以搭配正規表示法。

4.範例:

myfile.txt內容:

abcdefg

hijklmn

opqrst

uvwxyz

範例1:sed ‘1,3d’ myfile.txt  #刪除第一行到第三行的內容

輸出:uvwxyz

其中1,3d中的d表示刪除,而d前面的表示刪除的行的地址,而1,3表示一個地址範圍,也就是刪除第1行和第2行。地址範圍的表示一般是  m,n 表示對m和n行之間的所有行進行操作。sed的地址定址中可以使用$表示最後一行,例如 m,$ 表示對m行以及其後面的所有行進行操作。m,$d就是刪除m行以及其後面的所有行內容。當然我們還可以對某一行進行操作,例如2d表示僅僅刪除第2行。除了使用數字範圍 m,n 表示多行區間,以及m表示單行以外,我們還可以使用正則表示式選出符合條件的行,並對這些行進行操作。

注:這隻影響到輸出流,myfile.txt的第一行到第三行並沒有被刪除。

範例2:sed  -i ‘1,3d’ myfile.txt  #直接刪除第一行到第三行的內容, 不輸出到終端

範例3:sed '1a Hello World!' myfile.txt  #新增行

a命令表示在指定行的後面附加一行,1a則是在第一行的後面新增一行,新增的內容就是a後面的內容,如果a的前面沒有地址限定則在所有行的後面都會新增指定的字串。

範例4:sed '1c Hello World' myfile.txt  #替換行

命令c會替換指定的行的所有內容,替換成其後面的字串,所有的新增,刪除,替換行,這些命令前面的地址修飾都可以指定地址空間,也都可以使用正則表示式,命令會應用在選出的符合地址條件的所有行上面,例如:

範例5:sed '/^h/c Hello World!' myfile.txt  #替換以h開頭的行,其內容是c命令後面的字串

abcdefg

Hello world!

opqrst

uvwxyz

範例6:sed 's/abc/ABC/'myfile.txt  #部分字串而不是整行

執行的結果是我們檔案中的 abc 被替換成 ABC ,命令其含義:s/待替換的字串/新字串/ 也就是說使用後面的 AA 替換檔案中出現的前面的 aa。實際上這裡的替換僅僅替換每一行遇到的第一個aa,我們修改一下檔案的內容:

範例7:sed 's/aa/AA/g' myfile.txt #替換字串

最後一個斜槓後面g選項,表示進行全域性替換,也就是說所有符合條件的舊字串都會被替換成新字串。s命令也可以進行地址選擇,也就是在s的前面加上地址空間限定。

grep命令簡介

grep (global search regular expression(RE) and print out the line,全面搜尋正則表示式並把行打印出來)是一種強大的文字搜尋工具,它能使用正則表示式搜尋文字,並把匹配的行打印出來。在某個目錄下的文字檔案中查詢一個字串,可以使用‘grep’命令;‘grep’在幾個文字中搜索指定的字串。

例如正在‘/user/code’目錄下搜尋帶字串‘stdio’的檔案:

例1:grep stdio [./]usr/code/*

預設情況下,‘grep’只搜尋當前目錄。明確要求搜尋子目錄:grep –r

例2:grep –r stdio [./]usr/code/* 忽略子目錄:grep -d skip

例3:grep –d skip stdio [./]usr/code/* (與grep stdio [./]usr/code/*效果一樣)

注:搜尋當前目錄與子目錄:grep –r stdio *

當然,如果預料到有許多輸出,您可以將其轉到‘less’上閱讀:

3. 特殊的–在多個檔案中進行查詢 例4:grep “stdio”  *.c   ( #在當前目錄下所有.c檔案中查詢字串”stdio”)  

例5:grep –r stdio [./]usr/code/* | less

less是用來分頁顯示內容的一個 命令,其最基本的用法為:

less filename,例如: less text.txt

less的翻頁,查詢操作:

q:退出;空格:下一頁;b:上一頁;g:到第一行;G:到結尾。

‘*’ 表示搜尋全部檔案,如果不全部搜尋的話,必需提供一個檔案過濾方式。

grep –i string 檔案所在目錄/*:不區分大小寫地搜尋。預設情況區分大小寫,

grep -l string 檔案所在目錄/*:只列出匹配的檔名,

grep –L string 檔案所在目錄/*:列出不匹配的檔名,

grep –w string 檔案所在目錄/*:只匹配整個單詞,而不是字串的一部分

grep -C number:匹配的上下文分別顯示[number]行,

這裡還有些用於搜尋的特殊符號:

\< 和 \> 分別標註單詞的開始與結尾。

例如:

grep man * 會匹配 ‘Batman’、‘manic’、‘man’等,

grep '\<man' * 匹配‘manic’和‘man’,但不是‘Batman’,

grep '\<man\>' 只匹配‘man’,而不是‘Batman’或‘manic’等其他的字串。