Linux三個(gè)關(guān)鍵指令(grep|sed|awk)

文件處理

GREP

Linux命令行大全-grep:https://man.linuxde.net/grep

簡(jiǎn)介

grep(global search regular expression(RE) and print out the line,全面搜索正則表達(dá)式并把行打印出來(lái))是一種強(qiáng)大的文本搜索工具,它能使用正則表達(dá)式搜索文本,并把匹配的行打印出來(lái)。

選項(xiàng)

-a 不要忽略二進(jìn)制數(shù)據(jù)。
-A<顯示列數(shù)> 除了顯示符合范本樣式的那一行之外,并顯示該行之后的內(nèi)容。
-b 在顯示符合范本樣式的那一行之外,并顯示該行之前的內(nèi)容。
-c 計(jì)算符合范本樣式的列數(shù)。
-C<顯示列數(shù)>或-<顯示列數(shù)> 除了顯示符合范本樣式的那一列之外,并顯示該列之前后的內(nèi)容。
-d<進(jìn)行動(dòng)作> 當(dāng)指定要查找的是目錄而非文件時(shí),必須使用這項(xiàng)參數(shù),否則grep命令將回報(bào)信息并停止動(dòng)作。
-e<范本樣式> 指定字符串作為查找文件內(nèi)容的范本樣式。
-E 將范本樣式為延伸的普通表示法來(lái)使用,意味著使用能使用擴(kuò)展正則表達(dá)式。
-f<范本文件> 指定范本文件,其內(nèi)容有一個(gè)或多個(gè)范本樣式,讓grep查找符合范本條件的文件內(nèi)容,格式為每一列的范本樣式。
-F 將范本樣式視為固定字符串的列表。
-G 將范本樣式視為普通的表示法來(lái)使用。
-h 在顯示符合范本樣式的那一列之前,不標(biāo)示該列所屬的文件名稱(chēng)。
-H 在顯示符合范本樣式的那一列之前,標(biāo)示該列的文件名稱(chēng)。
-i 忽略字符大小寫(xiě)的差別。
-l 列出文件內(nèi)容符合指定的范本樣式的文件名稱(chēng)。
-****L 列出文件內(nèi)容不符合指定的范本樣式的文件名稱(chēng)。
-n 在顯示符合范本樣式的那一列之前,標(biāo)示出該列的編號(hào)。
-q 不顯示任何信息。
-R/-r 此參數(shù)的效果和指定“-d recurse”參數(shù)相同。
-s 不顯示錯(cuò)誤信息。
-v 反轉(zhuǎn)查找。
-w 只顯示全字符合的列。
-x 只顯示全列符合的列。
-y 此參數(shù)效果跟“-i”相同。
-o 只輸出文件中匹配到的部分。

grep命令常見(jiàn)用法

在文件中搜索一個(gè)單詞,命令會(huì)返回一個(gè)包含“match_pattern”的文本行:

grep match_pattern file_name
grep "match_pattern" file_name

在多個(gè)文件中查找:
grep "match_pattern" file_1 file_2 file_3 ...

輸出除之外的所有行 **-v **選項(xiàng):
grep -v "match_pattern" file_name

標(biāo)記匹配顏色 --color=auto 選項(xiàng):
grep "match_pattern" file_name --color=auto

使用正則表達(dá)式 -E 選項(xiàng):
grep -E "[1-9]+"

egrep "[1-9]+"

只輸出文件中匹配到的部分 **-o **選項(xiàng):
echo this is a test line. | grep -o -E "[a-z]+."
line.
echo this is a test line. | egrep -o "[a-z]+."
line.

統(tǒng)計(jì)文件或者文本中包含匹配字符串的行數(shù) -c 選項(xiàng):
grep -c "text" file_name

輸出包含匹配字符串的行號(hào) **-n **選項(xiàng):
grep "text" -n file_name

cat file_name | grep "text" -n

多個(gè)文件
grep "text" -n file_1 file_2

打印樣式匹配所位于的字符或字節(jié)偏移:
echo gun is not unix | grep -b -o "not"
7:not

一行中字符串的字符便宜是從該行的第一個(gè)字符開(kāi)始計(jì)算,起始值為0。選項(xiàng) -b -o 一般總是配合使用。
搜索多個(gè)文件并查找匹配文本在哪些文件中:
grep -l "text" file1 file2 file3...

grep遞歸搜索文件

在多級(jí)目錄中對(duì)文本進(jìn)行遞歸搜索:
grep "text" . -r -n

.表示當(dāng)前目錄。

忽略匹配樣式中的字符大小寫(xiě):
echo "hello world" | grep -i "HELLO"
hello
選項(xiàng)** -e** 制動(dòng)多個(gè)匹配樣式:
echo this is a text line | grep -e "is" -e "line" -o
is
line

也可以使用-f選項(xiàng)來(lái)匹配多個(gè)樣式,在樣式文件中逐行寫(xiě)出需要匹配的字符。
cat patfile
aaa
bbb
echo aaa bbb ccc ddd eee | grep -f patfile -o

在grep搜索結(jié)果中包括或者排除指定文件:
只在目錄中所有的.php和.html文件中遞歸搜索字符"main()"
grep "main()" . -r --include *.{php,html}

在搜索結(jié)果中排除所有README文件
grep "main()" . -r --exclude "README"

在搜索結(jié)果中排除filelist文件列表里的文件
grep "main()" . -r --exclude-from filelist

使用0值字節(jié)后綴的grep與xargs
測(cè)試文件:
echo "aaa" > file1
echo "bbb" > file2
echo "aaa" > file3

grep "aaa" file* -lZ | xargs -0 rm

執(zhí)行后會(huì)刪除file1和file3,grep輸出用-Z選項(xiàng)來(lái)指定以0值字節(jié)作為終結(jié)符文件名(\0),xargs -0 讀取輸入并用0值字節(jié)終結(jié)符分隔文件名,然后刪除匹配文件,-Z通常和-l結(jié)合使用。

grep靜默輸出:
grep -q "test" filename
不會(huì)輸出任何信息,如果命令運(yùn)行成功返回0,失敗則返回非0值。一般用于條件測(cè)試。
打印出匹配文本之前或者之后的行:
顯示匹配某個(gè)結(jié)果之后的3行,使用 -A 選項(xiàng):
seq 10 | grep "5" -A 3
5
6
7
8

顯示匹配某個(gè)結(jié)果之前的3行,使用 -B 選項(xiàng):

seq 10 | grep "5" -B 3
2
3
4
5

顯示匹配某個(gè)結(jié)果的前三行和后三行,使用 -C 選項(xiàng):
seq 10 | grep "5" -C 3
2
3
4
5
6
7
8

如果匹配結(jié)果有多個(gè),會(huì)用“--”作為各匹配結(jié)果之間的分隔符:
echo -e "a\nb[nc](http://man.linuxde.net/nc_netcat)\na\nb\nc" | grep a -A 1
a
b
--
a
b

SED

Linux命令大全-sed:https://man.linuxde.net/sed

簡(jiǎn)介

sed是一種流編輯器,它是文本處理中非常中的工具,能夠完美的配合正則表達(dá)式使用,功能不同凡響。處理時(shí),把當(dāng)前處理的行存儲(chǔ)在臨時(shí)緩沖區(qū)中,稱(chēng)為“模式空間”(pattern space),接著用sed命令處理緩沖區(qū)中的內(nèi)容,處理完成后,把緩沖區(qū)的內(nèi)容送往屏幕。接著處理下一行,這樣不斷重復(fù),直到文件末尾。文件內(nèi)容并沒(méi)有 改變,除非你使用重定向存儲(chǔ)輸出。Sed主要用來(lái)自動(dòng)編輯一個(gè)或多個(gè)文件;簡(jiǎn)化對(duì)文件的反復(fù)操作;編寫(xiě)轉(zhuǎn)換程序等。

sed的選項(xiàng)、命令、替換標(biāo)記

命令格式

sed [options] 'command' file(s)

sed [options] -f scriptfile file(s)

選項(xiàng)

-e<script>或--expression=<script>:以選項(xiàng)中的指定的script來(lái)處理輸入的文本文件;

-f<script文件>或--file=<script文件>:以選項(xiàng)中指定的script文件來(lái)處理輸入的文本文件;

-h或--help:顯示幫助;

-n或--quiet或——silent:僅顯示script處理后的結(jié)果;

-V或--version:顯示版本信息。

參數(shù)

文件:指定待處理的文本文件列表。

sed命令

*a* 在當(dāng)前行下面插入文本。

*i* 在當(dāng)前行上面插入文本。

*c* 把選定的行改為新的文本。

d 刪除,刪除選擇的行。

D 刪除模板塊的第一行。

s 替換指定字符

h 拷貝模板塊的內(nèi)容到內(nèi)存中的緩沖區(qū)。

H 追加模板塊的內(nèi)容到內(nèi)存中的緩沖區(qū)。

g 獲得內(nèi)存緩沖區(qū)的內(nèi)容,并替代當(dāng)前模板塊中的文本。

G 獲得內(nèi)存緩沖區(qū)的內(nèi)容,并追加到當(dāng)前模板塊文本的后面。

l 列表不能打印字符的清單。

n 讀取下一個(gè)輸入行,用下一個(gè)命令處理新的行而不是用第一個(gè)命令。

N 追加下一個(gè)輸入行到模板塊后面并在二者間嵌入一個(gè)新行,改變當(dāng)前行號(hào)碼。

p 打印模板塊的行。

P(大寫(xiě)) 打印模板塊的第一行。

q 退出Sed。

b lable 分支到腳本中帶有標(biāo)記的地方,如果分支不存在則分支到腳本的末尾。

r file 從file中讀行。

t label if分支,從最后一行開(kāi)始,條件一旦滿(mǎn)足或者T,t命令,將導(dǎo)致分支到帶有標(biāo)號(hào)的命令處,或者到腳本的末尾。

T label 錯(cuò)誤分支,從最后一行開(kāi)始,一旦發(fā)生錯(cuò)誤或者T,t命令,將導(dǎo)致分支到帶有標(biāo)號(hào)的命令處,或者到腳本的末尾。

w file 寫(xiě)并追加模板塊到file末尾。

W file 寫(xiě)并追加模板塊的第一行到file末尾。

! 表示后面的命令對(duì)所有沒(méi)有被選定的行發(fā)生作用。

= 打印當(dāng)前行號(hào)碼。

# 把注釋擴(kuò)展到下一個(gè)換行符以前。

sed替換標(biāo)記

g 表示行內(nèi)全面替換。

p 表示打印行。

w 表示把行寫(xiě)入一個(gè)文件。

x 表示互換模板塊中的文本和緩沖區(qū)中的文本。

y 表示把一個(gè)字符翻譯為另外的字符(但是不用于正則表達(dá)式)

\1 子串匹配標(biāo)記

& 已匹配字符串標(biāo)記

sed元字符集

^ 匹配行開(kāi)始,如:/^sed/匹配所有以sed開(kāi)頭的行。

**** 匹配行結(jié)束,如:/sed/匹配所有以sed結(jié)尾的行。

. 匹配一個(gè)非換行符的任意字符,如:/s.d/匹配s后接一個(gè)任意字符,最后是d。

***** 匹配0個(gè)或多個(gè)字符,如:/*sed/匹配所有模板是一個(gè)或多個(gè)空格后緊跟sed的行。

[] 匹配一個(gè)指定范圍內(nèi)的字符,如/[ss]ed/匹配sed和Sed。

[^] 匹配一個(gè)不在指定范圍內(nèi)的字符,如:/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一個(gè)字母開(kāi)頭,緊跟ed的行。

(..) 匹配子串,保存匹配的字符,如s/(love)able/\1rs,loveable被替換成lovers。

& 保存搜索字符用來(lái)替換其他字符,如s/love/&/,love這成love。

< 匹配單詞的開(kāi)始,如:/<love/匹配包含以love開(kāi)頭的單詞的行。

> 匹配單詞的結(jié)束,如/love>/匹配包含以love結(jié)尾的單詞的行。

x{m} 重復(fù)字符x,m次,如:/0{5}/匹配包含5個(gè)0的行。

x{m,} 重復(fù)字符x,至少m次,如:/0{5,}/匹配至少有5個(gè)0的行。

x{m,n} 重復(fù)字符x,至少m次,不多于n次,如:/0{5,10}/匹配5~10個(gè)0的行。

sed用法實(shí)例

替換操作:s命令

替換文本中的字符串:

sed 's/book/books/' file

-n選項(xiàng)p命令一起使用表示只打印那些發(fā)生替換的行:

sed -n 's/test/TEST/p' file

直接編輯文件選項(xiàng)-i,會(huì)匹配file文件中每一行的第一個(gè)book替換為books:

sed -i 's/book/books/g' file

舉例:樹(shù)莓派替換apt源

sudo sed -i 's#://raspbian.raspberrypi.org#s://mirrors.ustc.edu.cn/raspbian#g' /etc/apt/sources.list 
sudo sed -i 's#://archive.raspberrypi.org/debian#s://mirrors.ustc.edu.cn/archive.raspberrypi.org/debian#g' /etc/apt/sources.list.d/raspi.list

全面替換標(biāo)記g

使用后綴 /g 標(biāo)記會(huì)替換每一行中的所有匹配:

sed 's/book/books/g' file

當(dāng)需要從第N處匹配開(kāi)始替換時(shí),可以使用 /Ng:

echo sksksksksksk | sed 's/sk/SK/2g'

skSKSKSKSKSK

echo sksksksksksk | sed 's/sk/SK/3g'

skskSKSKSKSK

echo sksksksksksk | sed 's/sk/SK/4g'

skskskSKSKSK

定界符

以上命令中字符 / 在sed中作為定界符使用,也可以使用任意的定界符:

sed 's:test:TEXT:g'

sed 's|test|TEXT|g'

定界符出現(xiàn)在樣式內(nèi)部時(shí),需要進(jìn)行轉(zhuǎn)義:

sed 's//bin//usr/local/bin/g'

刪除操作:d命令

刪除空白行:

sed '/^$/d' file

刪除文件的第2行:

sed '2d' file

刪除文件的第2行到末尾所有行:

sed '2,$d' file

刪除文件最后一行:

sed '$d' file

刪除文件中所有開(kāi)頭是test的行:

sed '/^test/'d file

已匹配字符串標(biāo)記&

正則表達(dá)式 \w+ 匹配每一個(gè)單詞,使用 [&] 替換它,& 對(duì)應(yīng)于之前所匹配到的單詞:

echo this is a test line | sed 's/\w+/[&]/g'

[this] [is] [a] [test] [line]

所有以192.168.0.1開(kāi)頭的行都會(huì)被替換成它自已加localhost:

sed 's/^192.168.0.1/&localhost/' file

192.168.0.1localhost

子串匹配標(biāo)記\1

匹配給定樣式的其中一部分:

echo this is digit 7 in a number | sed 's/digit ([0-9])/\1/'

this is 7 in a number

命令中 digit 7,被替換成了 7。樣式匹配到的子串是 7,(..) 用于匹配子串,對(duì)于匹配到的第一個(gè)子串就標(biāo)記為 \1,依此類(lèi)推匹配到的第二個(gè)結(jié)果就是 \2,例如:

echo aaa BBB | sed 's/([a-z]+) ([A-Z]+)/\2 \1/'

BBB aaa

love被標(biāo)記為1,所有l(wèi)oveable會(huì)被替換成lovers,并打印出來(lái):

sed -n 's/(love)able/\1rs/p' file

組合多個(gè)表達(dá)式

sed '表達(dá)式' | sed '表達(dá)式'

等價(jià)于:

sed '表達(dá)式; 表達(dá)式'

引用

sed表達(dá)式可以使用單引號(hào)來(lái)引用,但是如果表達(dá)式內(nèi)部包含變量字符串,就需要使用雙引號(hào)。

test=hello

echo hello WORLD | sed "s/$test/HELLO"

HELLO WORLD

選定行的范圍:,(逗號(hào))

所有在模板test和check所確定的范圍內(nèi)的行都被打印:

sed -n '/test/,/check/p' file

打印從第5行開(kāi)始到第一個(gè)包含以test開(kāi)始的行之間的所有行:

sed -n '5,/^test/p' file

對(duì)于模板test和west之間的行,每行的末尾用字符串a(chǎn)aa bbb替換:

sed '/test/,/west/s/$/aaa bbb/' file

多點(diǎn)編輯:e命令

-e選項(xiàng)允許在同一行里執(zhí)行多條命令:

sed -e '1,5d' -e 's/test/check/' file

上面sed表達(dá)式的第一條命令刪除1至5行,第二條命令用check替換test。命令的執(zhí)行順序?qū)Y(jié)果有影響。如果兩個(gè)命令都是替換命令,那么第一個(gè)替換命令將影響第二個(gè)替換命令的結(jié)果。

和 -e 等價(jià)的命令是 --expression:

sed --expression='s/test/check/' --expression='/love/d' file

從文件讀入:r命令

file里的內(nèi)容被讀進(jìn)來(lái),顯示在與test匹配的行后面,如果匹配多行,則file的內(nèi)容將顯示在所有匹配行的下面:

sed '/test/r file' filename

寫(xiě)入文件:w命令

在example中所有包含test的行都被寫(xiě)入file里:

sed -n '/test/w file' example

追加(行下):a\命令

將 this is a test line 追加到 以test 開(kāi)頭的行后面:

sed '/^test/a\this is a test line' file

在 test.conf 文件第2行之后插入 this is a test line:

sed -i '2a\this is a test line' test.conf

插入(行上):i\命令

將 this is a test line 追加到以test開(kāi)頭的行前面:

sed '/^test/i\this is a test line' file

在test.conf文件第5行之前插入this is a test line:

sed -i '5i\this is a test line' test.conf

下一個(gè):n命令

如果test被匹配,則移動(dòng)到匹配行的下一行,替換這一行的aa,變?yōu)閎b,并打印該行,然后繼續(xù):

sed '/test/{ n; s/aa/bb/; }' file

變形:y命令

把1~10行內(nèi)所有abcde轉(zhuǎn)變?yōu)榇髮?xiě),注意,正則表達(dá)式元字符不能使用這個(gè)命令:

sed '1,10y/abcde/ABCDE/' file

退出:q命令

打印完第10行后,退出sed

sed '10q' file

保持和獲?。篽命令和G命令

在sed處理文件的時(shí)候,每一行都被保存在一個(gè)叫模式空間的臨時(shí)緩沖區(qū)中,除非行被刪除或者輸出被取消,否則所有被處理的行都將 打印在屏幕上。接著模式空間被清空,并存入新的一行等待處理。

sed -e '/test/h' -e '$G' file

在這個(gè)例子里,匹配test的行被找到后,將存入模式空間,h命令將其復(fù)制并存入一個(gè)稱(chēng)為保持緩存區(qū)的特殊緩沖區(qū)內(nèi)。第二條語(yǔ)句的意思是,當(dāng)?shù)竭_(dá)最后一行后,G命令取出保持緩沖區(qū)的行,然后把它放回模式空間中,且追加到現(xiàn)在已經(jīng)存在于模式空間中的行的末尾。在這個(gè)例子中就是追加到最后一行。簡(jiǎn)單來(lái)說(shuō),任何包含test的行都被復(fù)制并追加到該文件的末尾。

保持和互換:h命令和x命令

互換模式空間和保持緩沖區(qū)的內(nèi)容。也就是把包含test與check的行互換:

sed -e '/test/h' -e '/check/x' file

腳本scriptfile

sed腳本是一個(gè)sed的命令清單,啟動(dòng)Sed時(shí)以-f選項(xiàng)引導(dǎo)腳本文件名。Sed對(duì)于腳本中輸入的命令非常挑剔,在命令的末尾不能有任何空白或文本,如果在一行中有多個(gè)命令,要用分號(hào)分隔。以#開(kāi)頭的行為注釋行,且不能跨行。

sed [options] -f scriptfile file(s)

打印奇數(shù)行或偶數(shù)行

方法1:

sed -n 'p;n' test.txt #奇數(shù)行

sed -n 'n;p' test.txt #偶數(shù)行

方法2:

sed -n '1~2p' test.txt #奇數(shù)行

sed -n '2~2p' test.txt #偶數(shù)行

打印匹配字符串的下一行

grep -A 1 SCC URFILE

sed -n '/SCC/{n;p}' URFILE

awk '/SCC/{getline; print}' URFILE

AWK

AWK官方手冊(cè):http://www.gnu.org/software/gawk/manual/gawk.html

AWK內(nèi)置函數(shù):https://www.runoob.com/w3cnote/awk-built-in-functions.html

AWK工作原理:https://www.runoob.com/w3cnote/awk-work-principle.html

本文參考:https://www.cnblogs.com/ggjucheng/archive/2013/01/13/2858470.html

簡(jiǎn)介

awk是一個(gè)強(qiáng)大的文本分析工具,相對(duì)于grep的查找,sed的編輯,awk在其對(duì)數(shù)據(jù)分析并生成報(bào)告時(shí),顯得尤為強(qiáng)大。簡(jiǎn)單來(lái)說(shuō)awk就是把文件逐行的讀入,以空格為默認(rèn)分隔符將每行切片,切開(kāi)的部分再進(jìn)行各種分析處理。

awk有3個(gè)不同版本: awk、nawk和gawk,未作特別說(shuō)明,一般指gawk,gawk 是 AWK 的 GNU 版本。

awk其名稱(chēng)得自于它的創(chuàng)始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首個(gè)字母。實(shí)際上 AWK 的確擁有自己的語(yǔ)言: AWK 程序設(shè)計(jì)語(yǔ)言 , 三位創(chuàng)建者已將它正式定義為“樣式掃描和處理語(yǔ)言”。它允許您創(chuàng)建簡(jiǎn)短的程序,這些程序讀取輸入文件、為數(shù)據(jù)排序、處理數(shù)據(jù)、對(duì)輸入執(zhí)行計(jì)算以及生成報(bào)表,還有無(wú)數(shù)其他的功能。

使用方法

<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">awk '{pattern + action}' {filenames} awk '條件1 {動(dòng)作 1} 條件 2 {動(dòng)作 2} …' 文件名 awk 'BEGIN{ commands } pattern{ commands } END{ commands }'</pre>

盡管操作可能會(huì)很復(fù)雜,但語(yǔ)法總是這樣,其中 pattern 表示 AWK 在數(shù)據(jù)中查找的內(nèi)容,而 action 是在找到匹配內(nèi)容時(shí)所執(zhí)行的一系列命令?;ɡㄌ?hào)({})不需要在程序中始終出現(xiàn),但它們用于根據(jù)特定的模式對(duì)一系列指令進(jìn)行分組。 pattern就是要表示的正則表達(dá)式,用斜杠括起來(lái)。

awk語(yǔ)言的最基本功能是在文件或者字符串中基于指定規(guī)則瀏覽和抽取信息,awk抽取信息后,才能進(jìn)行其他文本操作。完整的awk腳本通常用來(lái)格式化文本文件中的信息。

通常,awk是以文件的一行為處理單位的。awk每接收文件的一行,然后執(zhí)行相應(yīng)的命令,來(lái)處理文本。

調(diào)用awk

有三種方式調(diào)用awk

<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">1.命令行方式 awk [-F field-separator] 'commands' input-file(s) 其中,commands 是真正awk命令,[-F域分隔符]是可選的。 input-file(s) 是待處理的文件。 在awk中,文件的每一行中,由域分隔符分開(kāi)的每一項(xiàng)稱(chēng)為一個(gè)域。通常,在不指名-F域分隔符的情況下,默認(rèn)的域分隔符是空格。 2.shell腳本方式 將所有的awk命令插入一個(gè)文件,并使awk程序可執(zhí)行,然后awk命令解釋器作為腳本的首行,一遍通過(guò)鍵入腳本名稱(chēng)來(lái)調(diào)用。 相當(dāng)于shell腳本首行的:#!/bin/sh 可以換成:#!/bin/awk 3.將所有的awk命令插入一個(gè)單獨(dú)文件,然后調(diào)用: awk -f awk-script-file input-file(s) 其中,-f選項(xiàng)加載awk-script-file中的awk腳本,input-file(s)跟上面的是一樣的。</pre>

本章重點(diǎn)介紹命令行方式。

條件(Pattern):

一般使用關(guān)系表達(dá)式作為條件。這些關(guān)系表達(dá)式非常多,具體參考表1。

表 1 awk支持的主要條件類(lèi)型

<colgroup><col span="1" width="114"><col span="1" width="129"><col span="1" width="490"></colgroup>
| 條件類(lèi)型 | 條 件 | 說(shuō) 明 |
| awk保留字 | BEGIN | 在 awk 程序一開(kāi)始,尚未讀取任何數(shù)據(jù)之前執(zhí)行。BEGIN 后的動(dòng)作只在程序開(kāi)始時(shí)執(zhí)行一次 |
| awk保留字 | END | 在 awk 程序處理完所有數(shù)據(jù),即將結(jié)束時(shí)執(zhí)行?END 后的動(dòng)作只在程序結(jié)束時(shí)執(zhí)行一次 |
| 關(guān)系運(yùn)算符 | > | 大于 |
| < | 小于 |
| >= | 大于等于 |
| <= | 小于等于 |
| == | 等于。用于判斷兩個(gè)值是否相等。如果是給變童賦值,則使用"=” |
| != | 不等于 |
| A~B | 判斷字符串 A 中是否包含能匹配 B 表達(dá)式的子字符串 |
| A!~B | 判斷字符串 A 中是否不包含能匹配 B 表達(dá)式的子字符串 |
| 正則表達(dá)式 | /正則/ | 如果在“//”中可以寫(xiě)入字符,則也可以支持正則表達(dá)式 |

例如:

x>10:判斷變量 x 是否大于10;

x == y:判斷變量 x 是否等于變量 y;

A~B:判斷字符串 A 中是否包含能匹配 B 表達(dá)式的子字符串;

A!~B:判斷字符串 A 中是否不包含能匹配 B 表達(dá)式的子字符串;

動(dòng)作(Action):

  • 格式化輸出;
  • 流程控制語(yǔ)句;

我們先來(lái)學(xué)習(xí) awk 的基本用法,也就是只看看格式化輸出動(dòng)作是干什么的??纯催@個(gè)例子:

[root@localhost ~]# awk '{printf 2 "\t"6 "\n"}' student.txt

輸出第二列和第六列的內(nèi)容

Name Average

Liming 87.66

Sc 85.66

Gao 91.66

在這個(gè)例子中沒(méi)有設(shè)定任何的條件類(lèi)型,所以這個(gè)文件中的所有內(nèi)容都符合條件,動(dòng)作會(huì)無(wú)條件執(zhí)行。動(dòng)作是格式化輸出 printf,"2"和"6"分別代表第二個(gè)字段和第六個(gè)字段,所以這條 awk 命令會(huì)列出 student.txt 文件的第二個(gè)字段和第六個(gè)字段。

雖然都是截取列的命令,但是 awk 命令比 cut 命令智能多了,cut 命令是不能很好地識(shí)別空格作為分隔符的;而對(duì)于 awk 命令來(lái)說(shuō),只要分隔開(kāi),不管是空格還是制表符,都可以識(shí)別。比如剛剛截取 df 命令的結(jié)果時(shí),cut 命令已經(jīng)力不從心了,我們來(lái)看看 awk 命令,命令如下:

[root@localhost ~]#df -h | awk '{print 1 "\t"3}'

文件系統(tǒng) 已用

/dev/sda3 1.8G

tmpfs 0

/dev/sda1 26M

/dev/sr0 3.5G

在這兩個(gè)例子中,我們分別使用了 printf 動(dòng)作和 print 動(dòng)作。發(fā)現(xiàn)了嗎?如果使用 printf 動(dòng)作,就必須在最后加入"\n",因?yàn)?printf 只能識(shí)別標(biāo)準(zhǔn)輸出格式;如果我們不使用"\n",它就不會(huì)換行。而 print 動(dòng)作則會(huì)在每次輸出后自動(dòng)換行,所以不用在最后加入"\n"。

入門(mén)實(shí)例

假設(shè)last -n 5的輸出如下

<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">[root@www ~]# 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)</pre>

如果只是顯示最近登錄的5個(gè)帳號(hào)

<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">#last -n 5 | awk '{print $1}' root root root dmtsai root</pre>

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

如果只是顯示/etc/passwd的賬戶(hù)

<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">#cat /etc/passwd |awk -F ':' '{print $1}' root daemon bin sys</pre>

這種是awk+action的示例,每行都會(huì)執(zhí)行action{print $1}。

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

如果只是顯示/etc/passwd的賬戶(hù)和賬戶(hù)對(duì)應(yīng)的shell,而賬戶(hù)與shell之間以tab鍵分割

<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">#cat /etc/passwd |awk -F ':' '{print 1"\t"7}' root /bin/bash daemon /bin/sh bin /bin/sh sys /bin/sh</pre>

如果只是顯示/etc/passwd的賬戶(hù)和賬戶(hù)對(duì)應(yīng)的shell,而賬戶(hù)與shell之間以逗號(hào)分割,而且在所有行添加列名name,shell,在最后一行添加"blue,/bin/nosh"。

<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">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</pre>

awk工作流程是這樣的:先執(zhí)行BEGIN,然后讀取文件,讀入有/n換行符分割的一條記錄,然后將記錄按指定的域分隔符劃分域,填充域,0則表示所有域,1表示第一個(gè)域,$n表示第n個(gè)域,隨后開(kāi)始執(zhí)行模式所對(duì)應(yīng)的動(dòng)作action。接著開(kāi)始讀入第二條記錄······直到所有的記錄都讀完,最后執(zhí)行END操作。

搜索/etc/passwd有root關(guān)鍵字的所有行

<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">#awk -F ':' '/root/' /etc/passwd root:x:0:0:root:/root:/bin/bash 注意:① /正則表達(dá)式/ ②-F ':'可簡(jiǎn)化為 -F : 或者 -F:</pre>

這種是pattern的使用示例,匹配了pattern(這里是root)的行才會(huì)執(zhí)行action(沒(méi)有指定action,默認(rèn)輸出每行的內(nèi)容)。

搜索支持正則,例如找root開(kāi)頭的: awk -F ':' '/^root/' /etc/passwd

搜索/etc/passwd有root關(guān)鍵字的所有行,并顯示對(duì)應(yīng)的shell

<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);"># awk -F ':' '/root/{print $7}' /etc/passwd /bin/bash</pre>

這里指定了action{print $7}

awk內(nèi)置變量

awk有許多內(nèi)置變量用來(lái)設(shè)置環(huán)境信息,這些變量可以被改變,下面給出了最常用的一些變量。

<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">ARGC 命令行參數(shù)個(gè)數(shù) ARGV 命令行參數(shù)排列 ENVIRON 支持隊(duì)列中系統(tǒng)環(huán)境變量的使用 FILENAME awk瀏覽的文件名 FNR 瀏覽文件的記錄數(shù) FS 設(shè)置輸入域分隔符,等價(jià)于命令行 -F選項(xiàng) NF 瀏覽記錄的域的個(gè)數(shù) NR 已讀的記錄數(shù) OFS 輸出域分隔符 ORS 輸出記錄分隔符 RS 控制記錄分隔符</pre>

此外,0變量是指整條記錄。1表示當(dāng)前行的第一個(gè)域,$2表示當(dāng)前行的第二個(gè)域,......以此類(lèi)推。

統(tǒng)計(jì)/etc/passwd:文件名,每行的行號(hào),每行的列數(shù),對(duì)應(yīng)的完整行內(nèi)容:

<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">#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</pre>

使用printf替代print,可以讓代碼更加簡(jiǎn)潔,易讀

<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">awk -F ':' '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd</pre>

print和printf

awk中同時(shí)提供了print和printf兩種打印輸出的函數(shù)。

其中print函數(shù)的參數(shù)可以是變量、數(shù)值或者字符串。字符串必須用雙引號(hào)引用,參數(shù)用逗號(hào)分隔。如果沒(méi)有逗號(hào),參數(shù)就串聯(lián)在一起而無(wú)法區(qū)分。這里,逗號(hào)的作用與輸出文件的分隔符的作用是一樣的,只是后者是空格而已。

printf函數(shù),其用法和c語(yǔ)言中printf基本相似,可以格式化字符串,輸出復(fù)雜時(shí),printf更加好用,代碼更易懂。

條件操作符

<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);"><、<=、==、!=、>=、匹配正則表達(dá)式、!不匹配正則表達(dá)式 匹配:awk ‘{if (4~/ASIMA/) print0}’ temp 表示如果第四個(gè)域包含ASIMA,就打印整條 精確匹配:awk ‘3==”48″ {print0}’ temp 只打印第3域等于”48″的記錄 不匹配: awk ‘0 !~ /ASIMA/’ temp 打印整條不包含ASIMA的記錄 不等于: awk ‘1 != “asima”‘ temp 小于: awk ‘{if (1<2) print 1 “is smaller”}’ temp 設(shè)置大小寫(xiě): awk ‘/[Gg]reen/’ temp 打印整條包含Green,或者green的記錄 任意字符: awk ‘1 ~/^…a/’ temp 打印第1域中第四個(gè)字符是a的記錄,符號(hào)’^’代表行首,符合’.’代表任意字符 或關(guān)系匹配: awk ‘0~/(abc)|(efg)/’ temp 使用|時(shí),語(yǔ)句需要括起來(lái) AND與關(guān)系: awk ‘{if (1==”a” && 2==”b” ) print0}’ temp OR或關(guān)系: awk ‘{if (1==”a” ||1==”b”) print $0}’ temp</pre>

自定義變量和賦值

除了awk的內(nèi)置變量,awk還可以自定義變量。

下面統(tǒng)計(jì)/etc/passwd的賬戶(hù)人數(shù)

<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">awk '{count++;print $0;} END{print "user count is ", count}' /etc/passwd root:x:0:0:root:/root:/bin/bash ...... user count is 40</pre>

count是自定義變量。之前的action{}里都是只有一個(gè)print,其實(shí)print只是一個(gè)語(yǔ)句,而action{}可以有多個(gè)語(yǔ)句,以;號(hào)隔開(kāi)。

這里沒(méi)有初始化count,雖然默認(rèn)是0,但是妥當(dāng)?shù)淖龇ㄟ€是初始化為0:

<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 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</pre>

統(tǒng)計(jì)某個(gè)文件夾下的文件占用的字節(jié)數(shù)

<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size}' [end]size is 8657198</pre>

如果以M為單位顯示:

<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size/1024/1024,"M"}' [end]size is 8.25889 M</pre>

注意,統(tǒng)計(jì)不包括文件夾的子目錄。

條件語(yǔ)句

awk中的條件語(yǔ)句是從C語(yǔ)言中借鑒來(lái)的,見(jiàn)如下聲明方式:

<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">if (expression) { statement; statement; ... ... } if (expression) { statement; } else { statement2; } if (expression) { statement1; } else if (expression1) { statement2; } else { statement3; }</pre>

統(tǒng)計(jì)某個(gè)文件夾下的文件占用的字節(jié)數(shù),過(guò)濾4096大小的文件(一般都是文件夾):

<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">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</pre>

循環(huán)語(yǔ)句

awk中的循環(huán)語(yǔ)句同樣借鑒于C語(yǔ)言,支持while、do/while、for、break、continue,這些關(guān)鍵字的語(yǔ)義和C語(yǔ)言中的語(yǔ)義完全相同。

數(shù)組

因?yàn)閍wk中數(shù)組的下標(biāo)可以是數(shù)字和字母,數(shù)組的下標(biāo)通常被稱(chēng)為關(guān)鍵字(key)。值和關(guān)鍵字都存儲(chǔ)在內(nèi)部的一張針對(duì)key/value應(yīng)用hash的表格里。由于hash不是順序存儲(chǔ),因此在顯示數(shù)組內(nèi)容時(shí)會(huì)發(fā)現(xiàn),它們并不是按照你預(yù)料的順序顯示出來(lái)的。數(shù)組和變量一樣,都是在使用時(shí)自動(dòng)創(chuàng)建的,awk也同樣會(huì)自動(dòng)判斷其存儲(chǔ)的是數(shù)字還是字符串。一般而言,awk中的數(shù)組用來(lái)從記錄中收集信息,可以用于計(jì)算總和、統(tǒng)計(jì)單詞以及跟蹤模板被匹配的次數(shù)等等。

顯示/etc/passwd的賬戶(hù)

<pre class="cm-s-default" style="color: rgb(89, 89, 89); margin: 0px; padding: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);">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 ......</pre>

這里使用for循環(huán)遍歷數(shù)組

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容