兩個概念,通配符與正則表達式,這兩個規範的實現都是由軟件所提供的,如通配符:shell和find,而它們的實現之間還有區別如:shell的[ ]裏面是不區分大小寫的。而find是區分大小寫的。linux
而正則表達式這一種更爲強大的搜索規範所使用的軟件如:vi,sed,grep,awk。
git
Linux上文本處理三劍客:
grep, egrep, fgrep:文本過濾工具(模式:pattern)工具;
grep:基本正則表達式,-E (egrep),-F(fgrep)
egrep:擴展正則表達式, -G(grep),-F(fgrep)
fgrep:不支持正則表達式,性能更好。
正則表達式
sed:stream editor, 流編輯器;文本編輯工具;
awk:Linux上的實現爲gawk,文本報告生成器(格式化文本);shell
使用:http://fanqie.blog.51cto.com/9382669/1650244express
正則表達式:Regual Expression, REGEXP
由一類特殊字符(元字符)及文本字符所編寫的模式,這些元字符不表示其字面意義,而是用於表示控制或通配的功能.
分兩類:
基本正則表達式:BRE
擴展正則表達式:ERE
緩存
目錄:bash
1、grepapp
一、正則表達式ssh
二、擴展正則表達式tcp
2、sed
1、grep
grep: Global search REgular expression and Print out the line.
做用:文本搜索工具,根據用戶指定的「模式(過濾條件)」對目標文本逐行進行匹配檢查;打印匹配到的行;
模式:由正則表達式的元字符及文本字符所編寫出的過濾條件;
正則表達式引擎;
grep [OPTIONS] PATTERN [FILE...]
grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]
OPTIONS:
--color=auto:對匹配到的文本着色後高亮顯示;
-i:ignorecase,忽略字符的大小寫;
-o:僅顯示匹配到的字符串自己;
-v, --invert-match:顯示不能被模式匹配到的行;
-E:支持使用擴展的正則表達式元字符;
-q, --quiet, --silent:靜默模式,即不輸出任何信息;
-A #:after, 後#行
-B #:before,前#行
-C #:context,先後各#行
一、基本正則表達式
字符匹配:
. | 點號匹配任意單個字符。 |
[] | 匹配裏面的任意單個字符,如:[acdb] a,c,d,b,這四個單字符都會匹配 |
[^] | 不匹配裏面的任意單個字符。跟上面徹底相反,這四個單字符都不會匹配。 |
上面的[ ]之間也能夠用下面這些字符組。它們表明一部分字符的組合。
[:upper:] 大寫字母
[:lower:] 小寫字母
[:alpha:] 全部字母
[:digit:] 全部數字
[:alnum:] 全部字母和數字
[:space:] 空格
[:punct:] 標點符號
如:查找大寫字母[[:upper:]]。裏面的[:upper:]是一個總體,與外面的[ ]沒有關係,因此不能省略。
次數匹配:用在要指定其出現的次數的字符的後面,用於限制其前面字符出現的次數;默認工做於貪婪模式;
* | 任意次前面的字符。包括0次。如:s* 沒有s的也會匹配。 |
.* | 只是一種應用方法,表明任意個任意字符。 |
\? | 前面字符的0次或1次。 |
\{m\} | 前面字符的m次。手動指定前面字符的次數。 |
\{m,n\} | 前面的字符的m-n次。如:\{2,3\} 2-8次前面的字符。 |
\{m,\} | 前面的字符至少m次。沒有上限,只有下限。 |
\{0,n\} | 前面的字符至多隻有n次。也就是從0到n個。 |
\+ | 前面的字符等於大於1次,與*相比,沒有0次了。 |
位置錨定:用於指定字符出現的位置。
^ | 指定行首 |
$ | 指定行尾 |
^$ | 這個只是一種應用方法, 表明空白行。 行首跟着行尾 空白行。 |
\<char | 查找以字符開頭的單詞。 用 \b 也行。 \bchar char是字符的意思。 |
char\> | 查找以字符結尾的單詞。 用\b 也行。 char\b |
組:
\(\) | 用於把單個字符組合成多個字符, 以組的方式再來次數匹配。 並且能夠被引用。 組的功能:一、把多個字符組合成總體來作次數匹配。二、能夠後向引用 |
\# | 後向引用。#爲數字,能夠引用第#個組的匹配結果,也就是第#個小括號。注意引用的是組所匹配到的結果,而不是把組的功能給複製過來。 |
\| |
或。如:"^abc|^def", 開頭是abc,或者開頭是def的。也能夠"^\(abc\|def\)" |
分組括號中的模式匹配 到的內容會被正則表達式引擎自動記錄於內部的變量中,這些變量爲:
\1:模式從左側起,第一個左括號以及與之匹配的右括號之間的模式所匹配到的字符;
\2:模式從左側起,第二個左括號以及與之匹配的右括號之間的模式所匹配到的字符;
...
關於後向引用。老師上課的時候,所給出的頗有意思的題。
找出先後同樣的love或者like。就是前是love後面就要是love.
He loves his lover.
He likes his lover.
She likes her liker.
She loves her liker.
~]# grep "\(l..e\).*\1" lovers.txt
例、查找下以 f 開頭,中間兩個任意字符,以 m 結尾的都有哪些。
[root@star-linux ~]# grep "f..m" text.tx
But from behind the walls of doubt
[root@star-linux ~]#
例、 第一個字符要麼是g 要麼是m,中間是兩個同樣的,結尾一個d,怎麼查 [ ] \{m\}
[root@star-linux ~]# grep "[gm].\{2\}d" text.tx
good morning everyone
I had a dream, I had an awesome dream
As we go down life's lonesome highway
[root@star-linux ~]#
結果出乎意料, 這是由於 . 是任意字符, 而\{2\} 是表明2個前面的字符,也就是兩個任意字符了(包括空格),這個題作的有問題。在要求先後同樣的狀況下,就要用到後向引用了。
例、用組和後向引用。\(\) \# 後向引用
[root@star-linux ~]# grep "[gm]\(.\)\1d" text.tx
good morning everyone
[root@star-linux ~]#
咱們要的是這個結果。 上面的意思就是小括號裏面的 . 所匹配到的是什麼結果,後面\1也就是什麼結果, 在個例子中,小括號是 o , 那麼 \1 也就是 o.
例、查找下行開頭是A 或者 As 。 ^ \?
[root@star-linux ~]# grep "^As\?" text.tx
And what they played
A voice was crying out
As we go down life's lonesome highway
[root@star-linux ~]#
例、再查找個單詞試試,way , 找這個單詞,那咱們就來試試。
[root@star-linux ~]# grep "way" text.tx
Say it for always
That's the way it should be
Say it for always
That's the way it should be
Say it for always
.........
[root@star-linux ~]#
What? 搞什麼仙人闆闆,把有關way的字符串都給拉出來了。 那麼 \< \>
[root@star-linux ~]# grep "\<way\>" text.tx
That's the way it should be
That's the way it should be
When you feel you've lost your way
That's the way it should be
That's the way it should be
[root@star-linux ~]#
\< \> 指定單詞用的,這兩個符號的兩邊只容許出現空格或者標點符號。若是是字母則不匹配。
例、查找以組爲單位的重複字符。組的次數匹配, \(\) \{m,\}
[root@star-linux ~]# grep "\(way\)\{2,\}" text.tx
Say it for alway waywayway ways
[root@star-linux ~]#
這個意思就是,way這個總體,重複兩次到無限屢次。
例、再看看行尾是怎麼回事,查找行尾是 . 的,有意思吧,注意 . 但是元字符,意思就不用說了吧, 那怎麼讓它變成普通字符, 轉義字符\ $
[root@star-linux ~]# grep "\.$" text.tx
it's fine day today.
There are many birds flying in the sky.
[root@star-linux ~]#
\ 的功能就是轉義。把有意義的字符,轉成普通的。把普通字符轉成有意義的,固然若是是不折不扣的普通字符,再轉也沒用。
而在正則表達式裏的加\的元字符, 是由於規範的問題所致使的,在grep所用的正則表達式裏,那些須要加\的元字符,都是普通字符,須要加上\來轉義,若是不加的話,它就是普通字符。
而在egrep 所用的擴展的正則表達式中, 除了\< \>和後向引用還要用轉義外, 其它的都不用轉義了,
這又是另外的一種規範, 若是非要加轉義符, 反而又變成普通字符了。
二、擴展正則表達式
主要區別就是次數匹配的元字符不用加\了.
egrep:
支持擴展的正則表達式實現相似於grep文本過濾功能;grep -E
egrep [OPTIONS] PATTERN [FILE...]
選項:
-i, -o, -v, -q, -A, -B, -C
-G:支持基本正則表達式
元字符:
. | 任意單個字符 |
[] | 範圍內的任意單個字符 |
[^] | 範圍外的任意單個字符 |
次數匹配:
* | 匹配任意次前面的字符 |
? | 匹配0或1次前面的字符 |
+ | 匹配至少1次前面的字符 |
{m} | 匹配其前面的字符m次 |
{m,n} | 匹配其前面的字符m-n次 |
{m,} | 匹配其前面的字符至少m次 |
{0,n} | 至多n次 |
位置錨定:
^ | 行首 |
$ | 行尾 |
\<或\b | 詞首 |
\>或\b | 詞尾 |
分組:
( ) | 分組。 組的功能 一、把多個字符組合成總體來作次數匹配。二、能夠後向引用 |
| | 或者 a|b:a或者b;C|cat:C或cat |
(|) | 組中的或 (c|C)at:cat或Cat |
跟基本正則表達式,除了不用加\之外,沒有什麼其它的區別。這裏來些例子作些參考
取路徑基名:
匹配IP地址:
匹配1.0.0.1--223.255.255.254 IP地址的寫法
[root@localhost ~]# ifconfig | egrep '(\<(1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\>\.){3}\<(1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\>' inet 172.16.249.185 netmask 255.255.0.0 broadcast 172.16.255.255 inet 192.168.189.190 netmask 255.255.255.0 broadcast 192.168.189.255 inet 127.0.0.1 netmask 255.0.0.0
匹配IP地址通常也不必必定要匹配1-254之間。也能夠直接匹配0-999的數字。
[root@localhost ~]# ifconfig | grep -E --color=auto "\<([0-9]{1,3}\.){3}[0-9]{1,3}\>" inet 172.16.249.185 netmask 255.255.0.0 broadcast 172.16.255.255 inet 192.168.189.190 netmask 255.255.255.0 broadcast 192.168.189.255 inet 127.0.0.1 netmask 255.0.0.0
2、sed。
sed [OPTION]... 'script' [input-file] ...
script:地址定界編輯命令
經常使用選項:
-n:不輸出模式空間中的內容至屏幕;真實的效果就是不顯示沒有區配到的。若是編輯命令是p,那正好只顯示區配到的,若是是d,那就會什麼也不顯示了,由於區配到的給刪除了。
-e script, --expression=script:多點編輯;
-f /PATH/TO/SED_SCRIPT_FILE 從文件讀取命令,每行一個編輯命令;
-r, --regexp-extended:擴展的正則表達式
-i[SUFFIX], --in-place[=SUFFIX]:直接編輯原文件 ;
地址定界:
(1) 空地址:對全文進行處理;
(2) 單地址:
#:指定行;
/pattern/:被此模式所匹配到的每一行;
(3) 地址範圍
#,#:
#,+#:
#,/pat1/
/pat1/,/pat2/
$:最後一行;
(4) 步進:~
1~2:全部奇數行
2~2:全部偶數行
從第幾行開始,步長爲幾。如0~10,5~3。
編輯命令:
d:刪除;
p:顯示模式空間中的內容;
a \text:在行後面追加文本「text」,支持使用\n實現多行追加;
i \text:在行前面插入文本「text」,支持使用\n實現多行插入;
以上若是text以前沒有要顯示的空字符,能夠不用\.
c \text:把匹配到的行替換爲此處指定的文本「text」;
w /PATH/TO/SOMEFILE:保存模式空間匹配到的行至指定的文件中;
r /PATH/FROM/SOMEFILE:讀取指定文件的內容至當前文件被模式匹配到的行後面;文件合併;
=:爲模式匹配到的行打印行號;
!:條件取反;格式:!編輯命令;
s///:查找替換,其分隔符可自行指定,經常使用的有s@@@, s###等;
替換標記:
g:全局替換;
w /PATH/TO/SOMEFILE:將替換成功的結果保存至指定文件中;
p:顯示替換成功的行;
sed的工做方式:
每次在磁盤上讀取一個塊,要看讀取文件的範圍了。而後在內核所緩存的文件數據中按換行符一次讀取一行數據,放到sed本身的內存空間(模式空間)來等待處理。
但處理的時候卻還有點不同,會複製一份數據直接stdout(默認屏幕),一份處處理空間處理。
雖然畫的stdou與處理空間一點關係也沒有,但仍是有點關聯的。在用d編譯命令的時候,不會直接stdout。
地址定界:
例:輸出passwd文件中的2-5行.
[root@localhost ~]# sed -n '2,5p' /etc/passwd bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin [root@localhost ~]#
通常狀況下,每行數據都會直接stdout出來。-n就是不要stdout。因此上面顯示的只有處理完成的數據。
上面的-n就是經常使用選項,而2,5的部分就是地址定界,p就是編輯命令。
地址定界也能夠用 /pattern/方式,如:
例:輸出root所在的數據。
[root@localhost ~]# sed -n '/root/p' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin [root@localhost ~]# sed -n '/^root\>/p' /etc/passwd root:x:0:0:root:/root:/bin/bash [root@localhost ~]#
上面第一個例子由於/pattern/寫的不夠嚴謹,因此匹配到了兩行。
例:顯示sshd用戶到最後一行。
[root@localhost ~]# sed -n '/^sshd\>/,$p' /etc/passwd sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin tcpdump:x:72:72::/:/sbin/nologin mageedu:x:1000:1000:MageEdu:/home/mageedu:/bin/bash sst:x:1001:1001::/home/sst:/bin/bash [root@localhost ~]#
顯示root和如下3行。
[root@localhost ~]# sed -n '/^root\>/,+3p' /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin [root@localhost ~]#
步進,從第幾行開始,每次跨幾行。如:
從20行開始,以3爲跨度。
[root@localhost ~]# sed -n '20~3p' /etc/passwd rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin chrony:x:996:994::/var/lib/chrony:/sbin/nologin ntp:x:38:38::/etc/ntp:/sbin/nologin
編輯命令中有個=號,是用來顯示所匹配到的數據的行號。
[root@localhost ~]# sed -n '20~3=' /etc/passwd 20 23 26
編輯命令:
上面的p和=號都有了,下面再來幾個。(a,i,c)
[root@localhost ~]# sed '/^root\>/a drink tea' /etc/passwd root:x:0:0:root:/root:/bin/bash drink tea bin:x:1:1:bin:/bin:/sbin/nologin
在root所在行的下面附加一行。a就是這個功能。
添加多行。單引號是絕對引用因此回車也能夠被sed識別,用\n表明換行也能夠。若是不定界,就是空地址,會在全部行的下面加上這一堆數據。
[root@localhost ~]# sed '2a drink tea\ > drink coffee\ > drink apple juicd' /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin drink tea drink coffee drink apple juicd
而i就是在root行的下面插入一行。
[root@localhost ~]# sed '/^root\>/i drink tea' /etc/passwd drink tea root:x:0:0:root:/root:/bin/bash
而c就是直接修改root行。
[root@localhost ~]# sed '/^root\>/c drink tea' /etc/passwd drink tea bin:x:1:1:bin:/bin:/sbin/nologin
編輯命令:d
sed '2d' 刪除第二行
sed '2,5d' 刪除2到5行
sed '2,$d' 刪除2到尾行
sed '/star/d' 刪除有star的行
編輯命令:s
sed '行號s/老的字符串/新的字符串/g'
以行單位查找匹配的字符串,而後替換。
sed 's/:/?/g' 把數據中全部行的:變成?。
sed '2,5s/:/?/g' 把2-5行的:變成?。
sed '/star/s/#/#star/g' 把有star的行中的#變成#star。
刪除/etc/fstab文件中全部以#開頭的行的行首的#號及#後面的全部空白字符;而且刪除空行。
[root@localhost ~]# sed -e 's/^#[[:space:]]*//g' -e '/^$/d' /etc/fstab /etc/fstab Created by anaconda on Sun Dec 6 11:02:42 2015 Accessible filesystems, by reference, are maintained under '/dev/disk' See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info UUID=1f89bbf3-c25c-4b4b-aac8-284c19077770 / xfs defaults 0 0 UUID=1591ce0b-5726-4e03-8cbe-0a2105169930 /boot xfs defaults 0 0 UUID=0a527ef7-eb80-4155-9cd5-ea12fba99515 /usr xfs defaults 0 0 UUID=7f892a1b-055a-498f-a812-64086132157a swap swap defaults 0 0 [root@localhost ~]#
輸出一個絕對路徑給sed命令,取出其目錄,其行爲相似於dirname;
[root@localhost ~]# echo "/etc/sysconfig/network-scripts/ifcfg-eno16777736/" | sed -r 's/[^\/]+\/?$//' /etc/sysconfig/network-scripts/ [root@localhost ~]#
把/etc/fstab文件中的全部UUID的行,最後面的0變成1.
[root@localhost ~]# sed -r '/^UUID\>/s/0([[:space:]]*)$/1\1/g' /etc/fstab # # /etc/fstab # Created by anaconda on Sun Dec 6 11:02:42 2015 # # Accessible filesystems, by reference, are maintained under '/dev/disk' # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info # UUID=1f89bbf3-c25c-4b4b-aac8-284c19077770 / xfs defaults 0 1 UUID=1591ce0b-5726-4e03-8cbe-0a2105169930 /boot xfs defaults 0 1 UUID=0a527ef7-eb80-4155-9cd5-ea12fba99515 /usr xfs defaults 0 1 UUID=7f892a1b-055a-498f-a812-64086132157a swap swap defaults 0 1
取出/boot/grub/grub.conf文件中的內核文件名稱。
[root@localhost ~]# sed -n 's/^[[:space:]]\+kernel \/\(vmlinuz[^[:space:]]\+\).*$/\1/p' /boot/grub/grub.conf vmlinuz-2.6.32-573.el6.x86_64 [root@localhost ~]#
謝謝瀏覽,有什麼不對的地方,還請指出。謝謝。