awk、grep、sed是linux操作文本的三大利器,合稱(chēng)文本三劍客,也是必須掌握的linux命令之一。三者的功能都是處理文本,但側(cè)重點(diǎn)各不相同,其中屬awk功能最強(qiáng)大,但也最復(fù)雜。grep更適合單純的查找或匹配文本,sed更適合編輯匹配到的文本,awk更適合格式化文本,對(duì)文本進(jìn)行較復(fù)雜格式處理。
grep
Linux 系統(tǒng)中 grep 命令是一種強(qiáng)大的文本搜索工具,它能使用正則表達(dá)式搜索文本,并把匹配的行打印出來(lái)。grep全稱(chēng)是 Global Regular Expression Print,表示全局正則表達(dá)式版本,它的使用權(quán)限是所有用戶(hù)。
grep可用于shell腳本,因?yàn)間rep通過(guò)返回一個(gè)狀態(tài)值來(lái)說(shuō)明搜索的狀態(tài),如果模板搜索成功,則返回0,如果搜索不成功,則返回1,如果搜索的文件不存在,則返回2。我們利用這些返回值就可進(jìn)行一些自動(dòng)化的文本處理工作。
命令的基本格式:
grep [option] pattern file
即便不熟悉這個(gè)命令,應(yīng)該大多數(shù)同學(xué)也用過(guò)查詢(xún)進(jìn)程的命令:
ps -ef|grep xxxx
這就是 grep 的一個(gè)基本用法,從所有進(jìn)程中搜索某個(gè)進(jìn)程。
grep 常用的參數(shù)如下:
- -A<行數(shù) x>:除了顯示符合范本樣式的那一列之外,并顯示該行之后的 x 行內(nèi)容。
- -B<行數(shù) x>:除了顯示符合樣式的那一行之外,并顯示該行之前的 x 行內(nèi)容。
- -C<行數(shù) x>:除了顯示符合樣式的那一行之外,并顯示該行之前后的 x 行內(nèi)容。
- -c:統(tǒng)計(jì)匹配的行數(shù)
- -e :實(shí)現(xiàn)多個(gè)選項(xiàng)間的邏輯or 關(guān)系
- -E:擴(kuò)展的正則表達(dá)式
- -f 文件名:從文件獲取?
PATTERN
?匹配 - -F :相當(dāng)于
fgrep
- -i --ignore-case #忽略字符大小寫(xiě)的差別。
- -n:顯示匹配的行號(hào)
- -o:僅顯示匹配到的字符串
- -q: 靜默模式,不輸出任何信息
- -s:不顯示錯(cuò)誤信息。
- -v:顯示不被?
pattern
?匹配到的行,相當(dāng)于[^] 反向匹配 - -w :匹配 整個(gè)單詞
前三個(gè) A、B、C 參數(shù)很容易理解,舉個(gè)栗子,假設(shè)我們有一個(gè)文件,文件名是 test,內(nèi)容是從 1 到 9,每個(gè)數(shù)字一行:
? grep -A2 7 test
7
8
9
-A2 7
?的效果就是找到 7 ,然后輸出 7 后面兩行。
同理,-B2 7
和-C2 7
就是找到 7 ,然后分別輸出 7 前面兩行和前后兩行:
? grep -B2 7 test
5
6
7
? grep -C2 7 test
5
6
7
8
9
繼續(xù),假設(shè)我們有個(gè)名叫 test 的文件內(nèi)容如下:
? cat test
aaaa
bbbbbb
AAAaaa
BBBBASDABBDA
grep -c
命令的作用就是輸出匹配到的行數(shù),比如我們想找包含aaa
的有幾行,一眼就能看出來(lái)有兩行,第一行和第三行都包含:
? grep -c aaa test
2
grep -e
命令是實(shí)現(xiàn)多個(gè)匹配之間的或
關(guān)系,比如我們想找包含aaaa
或者bbbb
的,顯然應(yīng)該返回第一行和第二行:
? grep -e aaaa -e bbbb test
aaaa
bbbbbb
grep -F
相當(dāng)于fgrep
命令,就是將pattern
視為固定字符串。比如搜索'aa*'
不帶-F
和帶上,區(qū)別如下:
? grep 'aa*' test
aaaa
AAAaaa
? grep -F 'aa*' test
可以看到第二次就找不到了,因?yàn)樗阉鞯氖?aa*
這個(gè)字符串,而不是正則表達(dá)式。
grep -f 文件名
的使用方法是把后面這個(gè)文件里的內(nèi)容當(dāng)做pattern
。比如我們有個(gè)文件,名字是 grep.txt,然后內(nèi)容是aa*
,使用方法如下:
? grep -f grep.txt test
aaaa
AAAaaa
實(shí)際上等同于grep 'aa*' test
grep -i --ignore-case
作用是忽略大小寫(xiě)。
grep -n
顯示匹配的行號(hào),就是多顯示了個(gè)行號(hào),不用細(xì)說(shuō)。
grep -o
僅顯示匹配到的字符串,還是用剛才的aa*
距離,之前顯示的都是匹配到的字符所在的整行,這個(gè)命令是只顯示匹配到的字符:
? grep -o 'aa*' test
aaaa
aaa
grep -q
不打印匹配結(jié)果。剛看到這個(gè)我疑惑了半天,讓你搜索字符串,你不給我結(jié)果那有啥用?然后發(fā)現(xiàn)還有一條很多教程沒(méi)說(shuō):如果有匹配的內(nèi)容則立即返回狀態(tài)值 0。所以一般用在shell
腳本中,在?if
?判斷里面。
grep -s
不顯示錯(cuò)誤信息,不解釋。
grep -v
顯示不被匹配到的行,相當(dāng)于[^]
反向匹配,最常見(jiàn)的還是用在查找線程的命令里,有時(shí)候會(huì)打印grep
線程,可以再加上這么一個(gè)去除自己:
? ps -ef|grep Typora
501 91616 1 0 五11上午 ?? 13:39.32 /Applications/Typora.app/Contents/MacOS/Typora
501 14814 93748 0 5:33下午 ttys002 0:00.00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn Typora
? ps -ef|grep Typora|grep -v grep
501 91616 1 0 五11上午 ?? 13:39.32 /Applications/Typora.app/Contents/MacOS/Typora
可以看到第二次就沒(méi)有打印grep
線程自身
grep -w
匹配整個(gè)單詞,只有完全符合pattern
的單次才會(huì)匹配到:
? grep aaa test
aaaa
AAAaaa
? grep -w aaa test
可以看到第二次結(jié)果為空,因?yàn)闆](méi)有aaa
這個(gè)單詞。
關(guān)于正則的高級(jí)用法就不再深入研究了,改日再統(tǒng)一整理。
sed
sed
?命令的作用是利用腳本來(lái)處理文本文件。使用方法:
sed [-hnV][-e<script>][-f<script文件>][文本文件]
參數(shù)說(shuō)明:
-
-e<script>
或--expression=<script>
?以選項(xiàng)中指定的?script
?來(lái)處理輸入的文本文件,這個(gè)-e
可以省略,直接寫(xiě)表達(dá)式。 -
-f<script文件>
或--file=<script文件>
以選項(xiàng)中指定的?script
?文件來(lái)處理輸入的文本文件。 -
-h
或--help
顯示幫助。 -
-n
?或?--quiet
?或?--silent
?僅顯示?script
?處理后的結(jié)果。 -
-V
?或?--version
?顯示版本信息。
動(dòng)作說(shuō)明:
- a:新增, a 的后面可以接字串,而這些字串會(huì)在新的一行出現(xiàn)(目前的下一行)~
- c:取代, c 的后面可以接字串,這些字串可以取代 n1,n2 之間的行!
- d:刪除,因?yàn)槭莿h除啊,所以 d 后面通常不接任何咚咚;
- i:插入, i 的后面可以接字串,而這些字串會(huì)在新的一行出現(xiàn)(目前的上一行);
- p:打印,亦即將某個(gè)選擇的數(shù)據(jù)印出。通常 p 會(huì)與參數(shù) sed -n 一起運(yùn)行~
- s:取代,通常這個(gè) s 的動(dòng)作可以搭配正規(guī)表示法,例如 1,20s/old/new/g 。
我們先準(zhǔn)備一個(gè)文件,名為test
做測(cè)試,內(nèi)容如下:
? cat test
HELLO LINUX!
Linux is a free unix-type opterating system.
This is a linux testfile!
Linux test
增加內(nèi)容
使用命令sed -e 3a\newLine testfile
這個(gè)命令的意思就是,在第三行后面追加newLine
這么一行字符,字符前面要用反斜線作區(qū)分。執(zhí)行完畢之后可以看到結(jié)果:
? sed -e 3a\newline test
HELLO LINUX!
Linux is a free unix-type opterating system.
This is a linux testfile!
newline
Linux test
但是注意,這個(gè)只是將文字處理了,沒(méi)有寫(xiě)入到文件里,文件里還是之前的內(nèi)容。
其實(shí) a 前面是可以匹配字符串,比如我們只想在出現(xiàn) Linux 的行后面追加,就可以:sed -e /Linux/a\newline test
?兩個(gè)斜線之間的內(nèi)容是需要匹配的內(nèi)容??梢钥闯?,只有第二、第四行有Linux
,所以結(jié)果如下:
? sed -e /Linux/a\newline test
HELLO LINUX!
Linux is a free unix-type opterating system.
newline
This is a linux testfile!
Linux test
newline
這里用雙引號(hào)把整個(gè)表達(dá)式括起來(lái)也可以,還方便處理帶空格的字符。
sed -e /Linux/a\newline test
等效于sed "/Linux/a newline" test
插入內(nèi)容
跟?a
?類(lèi)似,sed 3i\newline test
是在第三行前面插入newline
:
? sed 3i\newline test
HELLO LINUX!
Linux is a free unix-type opterating system.
newline
This is a linux testfile!
Linux test
sed /Linux/i\newline test
是在所有匹配到Linux
的行前面插入:
? sed /Linux/i\newline test
HELLO LINUX!
newline
Linux is a free unix-type opterating system.
This is a linux testfile!
newline
Linux test
可以看出插入的用法和增加很相似。
刪除
刪除的字符是d
,用法跟前面也很相似,就不贅述,例子如下:
? sed '/Linux/d' test
HELLO LINUX!
This is a linux testfile!
可以看到刪除了匹配到的兩行。
替換
替換也是一樣,字符是c
。舉個(gè)栗子:
? sed '/Linux/c\Windows' test
HELLO LINUX!
Windows
This is a linux testfile!
Windows
替換還有個(gè)字符是?s
,但是用法由不太一樣了,最常見(jiàn)的用法:sed 's/old/new/g'
其中old
代表想要匹配的字符,new
是想要替換的字符,比如:
? sed 's/Linux/Windows/g' test
HELLO LINUX!
Windows is a free unix-type opterating system.
This is a linux testfile!
Windows test
這里的/g
的意思是一行中的每一次匹配,因?yàn)橐恍兄锌赡芷ヅ涞胶芏啻巍N覀兡靡粋€(gè)新的文本文件做例子:
? cat test2
aaaaaaaaaaa
bbbbbabbbbb
cccccaacccc
假設(shè)我們想把一行中的第三次及以后出現(xiàn)的a
變成大寫(xiě)A
,那應(yīng)該這么寫(xiě):
? sed 's/a/A/3g' test2
aaAAAAAAAAA
bbbbbabbbbb
cccccaacccc
可以看出只有第一行的有的改了,因?yàn)榈诙谌袥](méi)有這么多a
出現(xiàn)。
關(guān)于s
還有很多用法,還是回到第一個(gè)文件,比如可以用/^/
和/$/
分別代表行首和行尾:
? sed 's/^/###/g' test
###HELLO LINUX!
###Linux is a free unix-type opterating system.
###This is a linux testfile!
###Linux test
? sed 's/$/---/g' test
HELLO LINUX! ---
Linux is a free unix-type opterating system. ---
This is a linux testfile! ---
Linux test ---
這個(gè)其實(shí)就是正則表達(dá)式的語(yǔ)法,其他類(lèi)似語(yǔ)法還有:
-
^
?表示一行的開(kāi)頭。如:/^#/
?以#開(kāi)頭的匹配。 -
$
?表示一行的結(jié)尾。如:/}$/
?以}結(jié)尾的匹配。 -
\<
?表示詞首。 如:`\ 表示以 abc 為首的詞。 -
\>
?表示詞尾。 如:abc\>
?表示以 abc 結(jié)尾的詞。 -
.
?表示任何單個(gè)字符。 -
*
?表示某個(gè)字符出現(xiàn)了0次或多次。 -
[ ]
?字符集合。 如:[abc]
?表示匹配a或b或c,還有?[a-zA-Z]
?表示匹配所有的26個(gè)字符。如果其中有^表示反,如?[^a]
?表示非a的字符
以上的所有用法,還可以在字符前面增加行號(hào)或者匹配。什么意思吶?比如你想在第一和第二行后面增加一行內(nèi)容newline
,就是:
? sed '1,2a\newline' test
HELLO LINUX!
newline
Linux is a free unix-type opterating system.
newline
This is a linux testfile!
Linux test
其他操作同理。不止可以用數(shù)字來(lái)限定范圍,還可以用匹配來(lái)限定,只需要用//
括起來(lái):
? sed '/LINUX/,/linux/i\test' test
test
HELLO LINUX!
test
Linux is a free unix-type opterating system.
test
This is a linux testfile!
Linux test
這里的意思是,從匹配到LINUX
的那一行,到匹配到linux
的那一行,也就是 123 這三行
,都做插入操作。
多個(gè)匹配
用-e
命令可以執(zhí)行多次匹配,相當(dāng)于順序依次執(zhí)行兩個(gè)sed
命令:
? sed -e 's/Linux/Windows/g' -e 's/Windows/Mac OS/g' test
HELLO LINUX!
Mac OS is a free unix-type opterating system.
This is a linux testfile!
Mac OS test
這個(gè)命令其實(shí)就是先把Linux
替換成Windows
,再把Windows
替換成Mac OS
。
寫(xiě)入文件
上面介紹的所有文件操作都支持在緩存中處理然后打印到控制臺(tái),實(shí)際上沒(méi)有對(duì)文件修改。想要保存到原文件的話可以用> file
或者-i
來(lái)保存到文件
awk
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)行各種分析處理。
語(yǔ)法
awk [選項(xiàng)參數(shù)] 'script' var=value file(s)
或
awk [選項(xiàng)參數(shù)] -f scriptfile var=value file(s)
參數(shù)說(shuō)明:
- -F fs or --field-separator fs 指定輸入文件折分隔符,fs是一個(gè)字符串或者是一個(gè)正則表達(dá)式,如-F:。
- -v var=value or --asign var=value 賦值一個(gè)用戶(hù)定義變量。
- -f scripfile or --file scriptfile 從腳本文件中讀取awk命令。
基本用法
最基本的用法是awk 動(dòng)作 文件名
。我們先準(zhǔn)備一個(gè)文件test
:
? cat test
2 this is a test
3 Are you like awk
This's a test
10 There are orange,apple,mongo
然后輸入awk '{print $1,$4}' test
就可以看到:
2 a
3 like
This's
10 orange,apple,mongo
對(duì)比可以很清楚的發(fā)現(xiàn),這行語(yǔ)句的作用是打印每行的第一個(gè)和第四個(gè)單詞。這里如果是$0
的話就是把整行都輸出出來(lái)。
awk -F
命令可以指定使用哪個(gè)分隔符,默認(rèn)是空格或者 tab 鍵:
? awk -F, '{print $2}' test
apple
可以看出只有最后一行有輸出,因?yàn)橛枚禾?hào)做分割,之后最后一行被分成了10 There are orange
、apple
和mongo
三項(xiàng),然后我們要的是第二項(xiàng)。
還可以同時(shí)使用多個(gè)分隔符:
? awk -F '[ ,]' '{print $1,$2,$5}' test
2 this test
3 Are awk
This's a
10 There apple
這個(gè)例子便是使用空格和逗號(hào)兩個(gè)分隔符。
匹配項(xiàng)中可以用正則表達(dá)式,比如:
? awk '/^This/' test
This's a test
匹配的就是嚴(yán)格以This
開(kāi)頭的內(nèi)容。
還可以取反:
? awk '$0 !~ /is/' test
3 Are you like awk
10 There are orange,apple,mongo
這一個(gè)的結(jié)果就是去掉帶有is
的行,只顯示其余部分。
從文件中讀取:awk -f {awk腳本} {文件名}
,這個(gè)很好理解,就不再做解釋。
變量
awk
中有不少內(nèi)置的變量,比如$NF
代表的是分割后的字段數(shù)量,相當(dāng)于取最后一個(gè)。
? awk '{print $NF}' test
test
awk
test
orange,apple,mongo
可以看出都是每行的最后一項(xiàng)。
其他的內(nèi)置變量還有:
-
FILENAME
:當(dāng)前文件名 -
FS
:字段分隔符,默認(rèn)是空格和制表符。 -
RS
:行分隔符,用于分割每一行,默認(rèn)是換行符。 -
OFS
:輸出字段的分隔符,用于打印時(shí)分隔字段,默認(rèn)為空格。 -
ORS
:輸出記錄的分隔符,用于打印時(shí)分隔記錄,默認(rèn)為換行符。 -
OFMT
:數(shù)字輸出的格式,默認(rèn)為%.6g
。
函數(shù)
awk
還提供了一些內(nèi)置函數(shù),方便對(duì)原始數(shù)據(jù)的處理。主要如下:
-
toupper()
:字符轉(zhuǎn)為大寫(xiě)。 -
tolower()
:字符轉(zhuǎn)為小寫(xiě)。 -
length()
:返回字符串長(zhǎng)度。 -
substr()
:返回子字符串。 -
sin()
:正弦。 -
cos()
:余弦。 -
sqrt()
:平方根。 -
rand()
:隨機(jī)數(shù)。
條件
awk
允許指定輸出條件,只輸出符合條件的行。輸出條件要寫(xiě)在動(dòng)作的前面:
awk '條件 動(dòng)作' 文件名
還是剛才的例子,用逗號(hào)分隔之后有好幾個(gè)空白行,我們加上限制條件,匹配后為空的不顯示:
? awk -F, '$2!="" {print $2}' test
apple
可以看到就只剩下apple
了。
if 語(yǔ)句
awk
提供了if
結(jié)構(gòu),用于編寫(xiě)復(fù)雜的條件。比如:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-798017.html
? awk '{if ($2 > "t") print $1}' test
2
這一句的完整含義應(yīng)該是:把每一行按照空格分割之后,如果第二個(gè)單詞大于t
,就輸出第一個(gè)單詞。這里對(duì)字符的大小判斷應(yīng)該是基于字符長(zhǎng)度和 unicode 編碼。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-798017.html
到了這里,關(guān)于Linux 文本處理三劍客:grep、sed 和 awk的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!