linux學習——shell腳本三劍客(grep、sed、awk)

awk、sed、grep綜述:

  • grep 更適合單純的查找或匹配文本
  • sed 更適合編輯匹配到的文本
  • awk 更適合格式化文本,對文本進行較復雜格式處理

1.Linux sed 命令

Linux sed命令是利用script來處理文本文件。
sed可依照script的指令,來處理、編輯文本文件。

sed主要用來:

  • 自動編輯一個或多個文件;
  • 簡化對文件的反復操作;
  • 編寫轉換程序等。

語法

sed [-hnV][-e<script>][-f<script文件>][文本文件]
參數說明
  • -e<script>或--expression=<script> 以選項中指定的script來處理輸入的文本文件。
  • -f<script文件>或--file=<script文件> 以選項中指定的script文件來處理輸入的文本文件。
  • -h或--help 顯示幫助
  • -n或--quit或--silent 僅顯示script處理后的結果
  • -V或--version 顯示版本信息
動作說明:
  • a:新增。a后面可以接字符串,而這些字符串會在新的一行出現(當前行的下一行)
  • c:取代。c的后面可以接字符串,這些字符串可以取代n1,n2之間的行
  • d:刪除。d的后面一般不接其他東西
  • i:插入。i的后面可以接字符串,而這些字符串會在新的一行出現(當前行的上一行)
  • p:打印。亦即將某個選擇的數據打印出來。通常p會與參數sed -n一起運行
  • s:取代。可以直接進行取代的工作。通常這個s的動作可以搭配正規表示法。例如1,20s/old/new/g

實例

在testfile文件的第四行后添加一行,并將結果輸出到標準輸出,在命令行提示符下輸入如下命令:

sed -e 4a\newLine testfile

首先查看testfile中的內容如下:

$ cat testfile
第一行
第二行
第三行
第四行
第五行

運行sed命令,輸出結果如下:

第一行
第二行
第三行
第四行
newline
第五行

以行為單位的新增/刪除

將 textfile 的內容列出并且列出行號,同時,請將第2~5行刪除:

$ nl testfile | sed '2,5d'
1   第一行

只刪除第二行:

$ nl testfile | sed '2d'
     1  第一行
     3  第三行
     4  第四行
     5  第五行

刪除從第三行開始的所有行:

$ nl testfile | sed '3,$d'
     1 第一行
     2 第二行

在第二行后(即加在第三行)加上[drink tea?]字樣!

$ nl testfile | sed '2a drink tea'
     1  第一行
     2  第二行
drink tea
     3  第三行
     4  第四行
     5  第五行

如果是要在第二行前:

$ nl  testfile | sed '2i drink tea'

如果是要增加兩行以上,比如在第二行后面加入兩行字『drink tea or ...』與『drink beer?』:

$ nl testfile | sed '2a drink tea or ...\
> drink beer ?'
     1  第一行
     2  第二行
drink tea or ...
drink beer ?
     3  第三行
     4  第四行
     5  第五行

每個行之間都必須要以反斜杠\來進行新行的添加。所以上面的例子中,我們可以發現在第一行的最后面就有\的存在。

以行為單位的替換與顯示

例如,將第2-5行的內容取代成為『No 2-5 number』:

$ nl testfile | sed '2,5c No 2-5 number'
     1  第一行
No 2-5 number

透過這個方法,我們就能將數據整行取代了。
僅列出testfile文件內的第2-4行:

$ nl testfile | sed -n '2,4p'
     2  第二行
     3  第三行
     4  第四行

可以透過這個sed的以行為單位的顯示功能,就能夠將某一個文件內的某些行號選擇出來顯示。

數據的搜尋并顯示

搜索testfile有"四"關鍵字的行

$ nl testfile | sed '/四/p'
     1  第一行
     2  第二行
     3  第三行
     4  第四行
     4  第四行
     5  第五行

可見找到匹配行后,除了輸出所有行,還會再次打印出此行。
使用-n的時候只會打印匹配的行。

$ nl testfile | sed -n '/四/p'
     4  第四行
數據的搜尋并刪除

刪除testfile所有包含'四'的行,其他行輸出:

$ nl testfile | sed '/四/d'
     1  第一行
     2  第二行
     3  第三行
     5  第五行
數據的搜尋并執行命令

搜索testfile,找到包含'四'的行,執行后面花括號中的一組命令,每個命令之間用分號分隔,這里把'行'替換為'列',再輸出這行:

$ nl testfile | sed -n '/四/{s/行/列/;p;q}'
     4  第四列

最后的q是退出。

數據的搜尋并替換

除了整行的處理模式之外,sed還可以用行為單位進行部分數據的搜尋并取代。基本上sed的搜尋與替代的與vi相當的類似,例如:

sed 's/要被取代的字符串/新的字符串/g'

利用/sbin/ifconfig查詢IP:
刪除IP前面部分的內容:

$ /sbin/ifconfig eth2 | grep 'inet addr' | sed 's/^.*addr://g'
192.168.80.100  Bcast:192.168.80.255  Mask:255.255.255.0

下面刪除后續部分內容:

$ /sbin/ifconfig eth2 | grep 'inet addr' | sed 's/^.*addr://g' | sed 's/Bcast.*$//'
192.168.80.100  
多點編輯

一條sed命令,刪除testfile第三行到末尾的行,并將"行"替換為"列"

$ nl testfile | sed -e '3,$d' | sed -e 's/行/列/'
     1  第一列
     2  第二列
直接修改文件內容(危險動作)

sed可以直接修改文件的內容,不必使用管道命令或數據量重導向。不過,由于這個動作會直接修改到原始的文件,所以請千萬不要隨便拿系統配置來測試。

利用sed將testfile內每一行的“行”修改為“列”:

$ sed -i 's/行/列/g' testfile
$cat testfile
第一列
第二列
第三列
第四列
第五列

利用sed直接在testfile最后一行加入"第六行":

$ sed -i '$a 第六行' testfile
$ cat testfile
第一列
第二列
第三列
第四列
第五列
第六行

由于$代表的是最后一行,而a的動作是新增,因此會增加在文件最后。
sed-i選項可以直接修改文件內容,這功能非常有幫助。舉例來說,如果你有一個100萬行的文件,你要在第100行加某些文字,此時使用vim可能會瘋掉,因為文件太大了。此時可以使用sed直接修改/取代。

2.Linux grep 命令

Linux grep命令用于查找文件里符合條件的字符串。
grep指令用于查找內容包含指定的范本樣式的文件,如果發現某文件的內容符合所指定的范本樣式,預設grep指令會把含有范本樣式的那一列顯示出來。若不指定任何文件名稱,或是所給予的文件名為"-",則grep指令會從標準輸入設備讀取數據。

語法

grep [-abcEFGhHilLnqrsvVwxy][-A<顯示列數>][-B<顯示列數>][-C<顯示列數>][-d<進行動作>][-e<范本樣式>][-f<范本文件>][--help][范本樣式][文件或目錄...]
參數:
  • -a 或 --text:不要忽略二進制的數據。
  • -A<顯示行數> 或 --after-context=<顯示行數>:除了顯示符合范本樣式的那一列之外,并顯示改行之后的內容。
  • -b 或 --byte-offset:在顯示符合樣式的那一行之前,標示出該行第一個字符的編號。
  • -B<顯示行數> 或 --before-context=<顯示行數>:除了顯示符合樣式的那一行之外,并顯示該行之前的內容。
  • -c 或 --count:計算符合樣式的列數。
  • -C<顯示行數> 或 --contest=<顯示行數> 或 -<顯示行數>:除了顯示符合樣式的那一行之外,并顯示該行之前后的內容。
  • -d<動作> 或 --directories=<動作>:當指定要查找的是目錄而非文件時,必須使用這項參數,否則grep指令將回報信息并停止動作。
  • -e<范本樣式> 或 --regexp=<范本樣式>:指定字符串作為查找文本內容的樣式。
  • -E 或 -extended-regexp:將樣式為延伸的普通表示法來使用。
  • -f<規則文件> 或 --file=<規則文件>:指定規則文件,其內容含有一個或多個規則樣式,讓grep查找符合規則條件的文件內容,格式為每行一個規則樣式。
  • -F 或 --fixed-regexp:將樣式視為固定字符串的列表。
  • -G 或 --basic-regexp:將樣式視為普通的表示法來使用。
  • -h 或 -no-filename:在顯示符合樣式的那一行之前,不標示該行所屬的文件名稱。
  • -H 或 --with-filename:在顯示符合樣式的那一行之前,標示該行所屬的文件名稱。
  • -i 或 --ignore-case:忽略字符大小寫的差別。
  • -I 或 --file-with-matches:列出文件內容符合指定的樣式的文件名稱。
  • -L 或 --file-without-match:列出文件內容不符合指定的樣式的文件名稱。
  • -n 或 --line-number:在顯示符合樣式的那一行之前,標示出該行的列數編號。
  • -q 或 --quiet 或 --silent:不顯示任何信息。
  • -r 或 -recursive:此參數的效果和指定-d recurse參數相同。
  • -s 或 --no-messages:不顯示錯誤信息。
  • -v 或 --revert-match:顯示不包含匹配文本的所有行。
  • -V 或 --version:顯示版本信息。
  • -w 或 --word-regexp:只顯示全字符合的列。
  • `-x 或 --line-regexp':只顯示全列符合的列。
  • -y:此參數的效果和指定-i參數相同。

實例:

  • 1.在當前目錄中,查找后綴有file字樣的文件中包含test字符串的文件,并打印出該字符串的行。此時,可以使用如下命令:
grep test *file

結果如下:

$ grep test *file
This is a test!
$ cat test testfile
第一列
第二列
第三列
第四列
第五列
第六行
This is a test!
  • 2.以遞歸方式查找符合條件的文件。例如,查找指定目錄及其子目錄(如果存在子目錄的話)下所有文件中包含字符串"conf"的文件,并打印出該字符串所在行的內容,使用的命令為:
$ grep -r conf /etc/acpi
/etc/acpi/events/power.conf:# ACPID config to power down machine if powerbutton is pressed, but only if
  • 3.反向查找。前面各個例子是查找并打印出符合條件的行,通過-v參數可以打印出不符合條件行的內容。
    例如,查找當前目錄中,文件名中包含test的文件中不包含test的行,此時,使用的命令為:
$ grep -v test *test*
test1.sh:#!/bin/bash
test1.sh:c1="shell"
test2.sh:#!/bin/bash
test2.sh:#或者使用以下包含文件代碼
test2.sh:echo "zkn在學習$c1"
testfile:第一列
testfile:第二列
testfile:第三列
testfile:第四列
testfile:第五列
testfile:第六行

3.Linux awk 命令

awk是一種處理文本文件的語言,是一個強大的文本分析工具。
之所以叫awk是因為其取了三位創始人Alfred Aho、Peter Weinberger和Barian Kernighan的Family Name的首字母。

語法

awk [選項參數] 'script' var=value file(s)
或
awk [選項參數] -f scriptfile var=value file(s)
選項參數說明:
  • -F fs 或 --file-separator fs 指定輸入文件拆分隔符,fs是一個字符串或者是一個正則表達式,如-F:
  • -v var=value 或 --asign var=value 賦值一個用戶定義變量
  • -f scripfile 或 --file scriptfile 從腳本文件中讀取awk命令。
  • -mf nnn 和 -mr nnnnnn值設置內在限制,-mf選項限制分配給nnn的最大塊數目;-mr選項限制記錄的最大數目。這兩個功能是Bell實驗室版awk的擴展功能,在標準awk中不適用。
  • -W compat 或 --compat ; -W traditional --traditional在兼容模式下運行awk。所以gawk的行為和標準的awk完全一樣,所有的awk擴展都被忽略。
  • -W copyleft 或 --copyleft ; -W copyright 或 --copyright 打印簡短的版權信息。
  • -W help 或 --help ; -W usage 或 --usage 打印全部awk選項和每個選項的簡短說明。
  • -W lint 或 --lint 打印不能向傳統unix平臺移植的結構的警告。
  • -W lint-old 或 --lint-old 打印關于不能向傳統unix平臺移植的結構的警告。
  • -W posix 打開兼容模式。但有以下限制:不識別/x、函數關鍵字、func、換碼序列以及當fs是一個空格時,將新行作為一個域分隔符;操作符**和**=不能代替=;fflush無效。
  • -W re-interval 或 --re-inerval 允許間隔正則表達式的使用,參考(grep中的Posix字符類),如括號表達式[[:alpha]]。
  • -W source program-text 或 --source program-text 使用program-text作為源代碼,可與-f命令混用。
  • -W version 或 --version 打印bug報告信息的版本。

基本用法

log.txt文本內容如下:

2 this is a test
3 Are you like awk
This's a test
10 There are orange,apple,mongo

用法一:

awk '{[pattern] action}' {filenames} #行匹配語句 awk '' 只能用單引號

實例:

# 每行按空格或TAB分割,輸出文本中的1/4項
$ awk '{print $1,$4}' log.txt
2 a
3 like
This's 
10 orange,apple,mongo
或
$ awk '{printf "%-8s %-10s\n",$1,$4}' log.txt
2        a         
3        like      
This's             
10       orange,apple,mongo

用法二:

awk -F #-F相當于內置變量F5,指定分割字符

實例:

### 使用","分割
$ awk -F: '{print $1,$2}' log.txt
2 this is a test 
3 Are you like awk 
This's a test 
10 There are orange,apple,mongo 
### 或者使用內建變量
$ awk 'GEGIN{FS=","}{print $1,$2}' log.txt
2 this
3 Are
This's a
10 There
### 使用多個分隔符。先使用空格分割,然后對分割結果再使用","分割
$ awk -F '[ ,]' '{print $1,$3,$5}' log.txt
2 is test
3 you awk
This's test 
10 are apple

用法三:

awk -v #設置變量

實例:

$ awk -va=1 '{print $1,$1+a}' log.txt
2 3
3 4
This's 1
10 11
$ awk -va=1 -vb=s '{print $1,$1+a,$1b}' log.txt
2 3 2s
3 4 3s
This's 1 This'ss
10 11 10s

用法四:

awk -f {awk腳本} {文件名}

實例:

$ awk -f cal.awk log.txt

運算符

運算符 描述
= += -= *= /= %= ^= **= 賦值
?: C條件表達式
|| 邏輯或
&& 邏輯與
~ ~! 匹配正則表達式和不匹配正則表達式
< <= > >= != == 關系運算符
空格 連接
+ - 加和減
* / % 乘、除和求余
+ - ! 一元加、減和邏輯非
^ *** 求冪
++ -- 增加或減少,作為前綴或后綴
$ 字段引用
in 數組成員

過濾第一列大于2的行:

$ awk '$1>2' log.txt
3 Are you like awk
This's a test
10 There are orange,apple,mongo

獲取第一列等于2的行:

$ awk '$1==2' log.txt
2 this is a test

獲取第一列大于2并且第二列等于'Are'的行:

$ awk '$1>2 && $2=="Are" ' log.txt
3 Are you like awk

內建變量

變量 描述
$n 當前記錄的第n個字段,字段間由FS分隔
$0 完整的輸入記錄
ARGC 命令行參數的數目
ARGIND 命令行中當前文件的位置(從0開始算)
ARGV 包含命令行參數的數組
CONVFMT 數字轉換格式(默認%.6g)ENVIRON環境變量關聯數組
ERROR 最后一個系統錯誤的描述
FIELDWIDTHS 字段寬度列表(用空格鍵分隔)
FILENAME 當前文件名
FNR 個文件分別計數的行數
FS 字段分隔符(默認是任何空格)
IGNORECASE 如果為真,則進行忽略大小寫的匹配
NF 一條記錄的字段的數目
NR 已經讀出的記錄數,就是行號,從1開始
OFMT 數字的輸出格式(默認是%.6g)
OFS 輸出記錄分隔符(輸出換行符),輸出時用指定的符號代替換行符
ORS 輸出記錄分隔符(默認是一個換行符)
RLENGTH 由match函數所匹配的字符串的長度
RS 記錄分隔符(默認是一個換行符)
RSTART 有match函數所匹配的字符串的第一個位置
SUBSEP 數組下標分隔符(默認值是/034)

使用正則字符串匹配

輸出第二列包含"th"的行,并打印第二列和第四列

$ awk '$2 ~ /th/ {print $2,$4}' log.txt
this a

~表示模式開始,//中是模式
輸出包含"re"的行

$ awk '/re/' log.txt
3 Are you like awk
10 There are orange,apple,mongo

忽略大小寫

$ awk 'BEGIN{IGNORECASE=1} /this/' log.txt #大寫和小寫的this均匹配出來了
2 this is a test
This's a test

模式取反

$ awk '$2 !~ /th/ {print $2,$4}' log.txt
Are like
a 
There orange,apple,mongo
$ awk '!/th/ {print $2,$4}' log.txt
Are like
a 
There orange,apple,mongo

awk腳本

關于awk腳本,我們需要注意兩個關鍵詞BEGINEND

  • BEGIN{這里面放的是執行前的語句}
  • END{這里面放的是處理完所有的行后要執行的語句}
  • {這里面放的是處理每一行時要執行的語句}
    假設有這么一個文件(學生成績表):
$ cat score.txt
Marry   2143 78 84 77
Jack    2321 66 78 45
Tom     2122 48 77 71
Mike    2537 87 97 95
Bob     2415 40 57 62

我們的awk腳本如下:

$ cat cal.awk
#!/bin/awk -f
#運行前
BEGIN {
    math = 0
    english = 0
    computer = 0
    printf "NAME   NO.    MATH 
   ENGLISH   COMPUTER   TOTAL\n"
}
#運行中
{
    math+=$3
    english+=$4
    computer+=$5
    printf "%-6s %-6s %4d %8d %8d %8d\n",$1,$2,$3,$4,$5,$3+$4+$5
}
#運行后
END{
    printf "TOTAL:%10d %8d %8d \n",math,english,computer
    printf "AVERAGE:%10.2f %8.2f %8.2f\n",math/NR,english/NR,computer/NR
}

下面看執行結果:

$ awk -f cal.awk score.txt
NAME   NO.    MATH   ENGLISH    COMPUTER    TOTAL
Marry  2143     78       84       77      239
Jack   2321     66       78       45      189
Tom    2122     48       77       71      196
Mike   2537     87       97       95      279
Bob    2415     40       57       62      159
TOTAL:       319      393      350 
AVERAGE:     63.80    78.60    70.00

另外一些實例

awk的hello world程序為:

BEGIN { print "Hello,World!"}

計算文件大小:

$ ls -l *.txt | awk '{sum+=$5} END {print sum}'
192

從文件中找出長度大于20的行:

$ awk 'length>20' log.txt
10 There are orange,apple,mongo

打印九九乘法口訣:

$ seq 9 | sed 'H;g' | awk -v RS=''  '{for(i=1;i<=NF;i++)printf("%dx%d=%d%s",i,NR,i*NR,i==NR?"\n":"\t")}'
1x1=1
1x2=2   2x2=4
1x3=3   2x3=6   3x3=9
1x4=4   2x4=8   3x4=12  4x4=16
1x5=5   2x5=10  3x5=15  4x5=20  5x5=25
1x6=6   2x6=12  3x6=18  4x6=24  5x6=30  6x6=36
1x7=7   2x7=14  3x7=21  4x7=28  5x7=35  6x7=42  7x7=49
1x8=8   2x8=16  3x8=24  4x8=32  5x8=40  6x8=48  7x8=56  8x8=64
1x9=9   2x9=18  3x9=27  4x9=36  5x9=45  6x9=54  7x9=63  8x9=72  9x9=81
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,030評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,310評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,951評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,796評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,566評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,055評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,142評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,303評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,799評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,683評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,899評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,409評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,135評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,520評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,757評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,528評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,844評論 2 372

推薦閱讀更多精彩內容