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 nnn
對nnn
值設置內在限制,-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腳本,我們需要注意兩個關鍵詞BEGIN
和END
。
-
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