Linux通配符與正則表達(dá)式的區(qū)別及使用說明
背景
在linux使用過程中,經(jīng)常需要查找文件,對命令中的通配符 pattern 和正則表達(dá)式的區(qū)分不是很清楚。有必要好好研究一下。
1 掃盲
通配符和正則表達(dá)式
當(dāng)在使用命令行時,有很多時間都用來查找你所需要的文件,如 ls find
等。 Shell 提供了一套完整的字符串模式匹配規(guī)則,或者稱之為元字符,當(dāng) Shell 遇到上述字符時,就會把它們當(dāng)作特殊字符,而不是文件名中的普通字符,這樣用戶就可以用它們來匹配相應(yīng)的文件名,我理解這可以稱為通配符。
通配符與正則表達(dá)式是有區(qū)別的,簡單來說:通配符是用來通配的,正則表達(dá)式是用來匹配字符串的;
通配符是shell自帶的用于匹配文件名的工具,多用在文件名上,比如查找find
,ls
,cp
等等,而正則表達(dá)式則需要特定命令的支持才可以使用,如:grep
、sed
和awk
(號稱Linux三劍客)、vi/vim
、perl
等,這些都是處理文本的工具。
其次,shell對通配符與正則表達(dá)式的處理也有不同,“ ”
內(nèi)一般為通配符(是shell本身提取處理),‘ ’
內(nèi)一般為正則表達(dá)式(shell會將其中的數(shù)據(jù)傳遞給其它命令處理)。
通配符
常見元字符:
*
:匹配零或多個任意字符?
:匹配任意單個字符[]
:指定中括號內(nèi)的多個字符,如:[rwc]或[r,w,c]都行[^]
或[!]
:除了中括號內(nèi)字符外匹配任一個字符
引用以下模式要在外面再套一個[],tr
命令則不用(這是規(guī)定嗎?)
[:digit:]
:匹配任意一個數(shù)字[:lower:]
:任意小寫字符[:upper:]
:任意大寫字符[:alpha:]
:任意大小寫字母[:alnum:]
:任意一個字母或數(shù)字[:space:]
:一個空格[:punct:]
:標(biāo)點(diǎn)符號
正則表達(dá)式
這里不具體介紹正則表達(dá)式,只是說一下和通配符的區(qū)別
首先通配符沒有次數(shù)匹配
*
:匹配前面的字符零次或多次.
:匹配任意一個字符?
:前面的字符零次或一次,基本正則是?+
:前面的字符至少一次,基本正則是+[]
:和通配符完全一樣[^]
:和通配符一樣,但是沒有[!]
的寫法
2 通配符詳細(xì)介紹
測試數(shù)據(jù)
touch a a6.log abc.log ac.txt b c c5.txt x.log A
*
代表任意多個字符
- 例:查詢以
.log
結(jié)尾的文件ll *.log
?
代表任意單個字符
- 例:只查詢
a、b、c
ll ?
[]
代表 [
和 ]
之間的某一個字符,比如[0-9]
可以代表0-9之間的任意一個數(shù)字,[a-zA-Z]
可以代表a-z
和A-Z
之間的任意一個字母,字母區(qū)分大小寫。
- 例:只查詢字母文件
ll [a-zA-Z]
- 例:查詢以
.log
結(jié)尾且.log
前只有兩個字符的文件且第二個字符是數(shù)字ll ?[0-9].log
^
表示匹配結(jié)果取反的意思,注意這個通配符必須要在[]中使用
- 例:查詢不是以
.txt
結(jié)尾的文件ll *[^txt]*
{}
表示符合括號內(nèi)包含的多個文件
- 例:查詢
.log
和.txt
結(jié)尾的文件ll {*.log,*.txt}
注意: .
這個符合比較特殊,如果匹配的條件加上了該符合那么說明查詢結(jié)果文件就包含帶.
的文件
例如前面的^
的例子,如果我這樣查詢ll *.[^txt]*
,那么結(jié)果就不一樣了
刪除操作
- 例如:刪除
a、b、c
和以.txt
結(jié)尾的文件
rm -f {[abc],*.txt}
當(dāng)然既然可以查詢當(dāng)然也可以使用通配符匹配的方式進(jìn)行移動文件,如果需要在存在很多文件的文件夾中移動某些類型的文件那么使用通配符匹配的效率就顯而易見了;當(dāng)時通配符的使用技巧不單單只有這些,有空的可以多去研究。
3 實例
*
匹配文件名中的任何字符串,包括空字符串。?
匹配文件名中的任何單個字符。[...]
匹配[ ]中所包含的任何字符。[!...]
匹配[ ]中非感嘆號!之后的字符。和^的效果一樣
如:
5*
5開頭的所有字符串*5
5結(jié)尾的所有字符串*5?
以5為倒數(shù)第二個字符的字符串[0-9]
所有以數(shù)字的字符[1,2]
1或者2[!0-9]
不是數(shù)字的字符ls /etc/[!a-n]*.conf
列出/etc/目錄中不是以字母a到n開頭的,并且以.conf結(jié)尾的文件ls /etc/[a-n]*.conf
列出/etc/目錄中以字母a到n開頭的,并且以.conf結(jié)尾的文件ls /bin/[ck]*
列出以 c或k開頭的文件名
4 正則表達(dá)式詳細(xì)介紹
正則表達(dá)式(也稱為“regex”或“regexp”)是一種用來描述文本模式的特殊語法。
在 Linux 系統(tǒng)上,正則表達(dá)式通常被用來查找文本的模式,以及對文本流執(zhí)行“搜索-替換”操作以及其它功能。
簡單字串
$ grep bash /etc/passwd operator:x:11:0:operator:/root:/bin/bash root:x:0:0::/root:/bin/bash ftp:x:40:1::/home/ftp:/bin/bash
在上面的命令中,grep 的第一個參數(shù)是一個正則表達(dá)式;第二個參數(shù)是一個文件名。grep 讀取 /etc/passwd 中的每一行并對它應(yīng)用簡單子串正則表達(dá)式 bash 來查找匹配項。如果找到一個匹配項,那么 grep 打印出整行;否則,忽略該行。
理解簡單子串
一般來說,如果您正在搜索一個子串,那么您可以不提供任何“特殊”字符,而只是逐字地指定文本。只有在子串包含 +
、.
、*
、[
、]
或 /
(在這樣的情況下,這些字符需要用引號括起來并在它們的前面使用反斜杠)才需要做特殊的事情。
下面是簡單子串正則表達(dá)式幾個其它示例:
tmp (掃描查找文字串 tmp) “\[box\]”(掃描查找文字串 [box]) “\*funny\*”(掃描查找文字串 *funny*) “l(fā)d\.so”(掃描查找文字串 ld.so)
元字符
使用正則表達(dá)式,可以利用元字符來執(zhí)行比我們至今已研究過的示例復(fù)雜得多的搜索。這些元字符中的一個是 .(點(diǎn)),它與任何單個字符匹配:
$ grep dev.hda /etc/fstab /dev/hda3 reiserfs noatime,ro 1 1 /dev/hda1 /boot reiserfs noauto,noatime,notail 1 2 /dev/hda2 swap sw 0 0 #/dev/hda4 /mnt/extra reiserfs noatime,rw 1 1
在本示例中,文字文本 dev.hda 沒有出現(xiàn)在 /etc/fstab 中的任何一行中。但是,grep 掃描這些行時沒有查找文字 dev.hda 字符串,而是查找 dev.hda 模式。請記住 . 將與任何單個字符相匹配。正如您看到的,. 元字符在功能上等價于 glob 擴(kuò)展中 ? 元字符的工作原理。
使用 []
如果我們希望與比 . 更具體一點(diǎn)地來匹配字符,那么我們可以使用 [ 和 ](方括號)來指定要匹配的字符子集:
$ grep dev.hda[12] /etc/fstab /dev/hda1 /boot reiserfs noauto,noatime,notail 1 2 /dev/hda2 swap swap sw 0 0
[\u4e00-\u9fa5]
: 表示任意一個漢字
正如您看到的,這個特殊語法的作用與glob
文件名擴(kuò)展中的 []
相同。
使用 [^]
通過使 [
后面緊跟一個 ^
,您可以使方括號中的意思相反。在本例中,方括號將與未列在方括號內(nèi)的任意字符匹配。同樣,請注意我們在正則表達(dá)式中使用 [^]
,而在 glob 中使用 [!]
:
$ grep dev.hda[^12] /etc/fstab /dev/hda3 reiserfs noatime,ro 1 1 /dev/hda4 /mnt/extra reiserfs noatime,rw 1 1
區(qū)別語法
注意下面一點(diǎn)很重要:方括號內(nèi)部的語法根本不同于正則表達(dá)式其它部分中的語法。
例如,如果在方括號內(nèi)放置一個 . ,那么它允許方括號與文字 . 匹配,就象上面示例中的 1 和 2。比較起來,除非有\(zhòng) 作為前綴,否則方括號外面的文字 . 被解釋為一個元字符。通過輸入如下命令,我們可以利用這一事實來打印 /etc/fstab 中包含文字串 dev.hda 的所有行的列表:
$ grep dev[.]hda /etc/fstab
或者,我們也可以輸入:
$ grep "dev\.hda" /etc/fstab
這兩個正則表達(dá)式都不可能與您的 /etc/fstab
文件中的任何行相匹配。
*
元字符
某些元字符本身不匹配任何字符,但卻修改前一個字符的含義。一個這樣的元字符是 *
(星號),它用來與前一個字符的零次或者多次重復(fù)出現(xiàn)相匹配。
這里是一些示例:
ab*c
(與abbbbc
匹配但不與abqc
匹配)ab*c
(與abc
匹配但不與abbqbbc
匹配)ab*c
(與ac
匹配但不與cba
匹配)b[cq]*e
(與bqe
匹配但不與eb
匹配)b[cq]*e
(與bccqqe
匹配但不與bccc
匹配)b[cq]*e
(與bqqcce
匹配但不與cqe
匹配)b[cq]*e
(與bbbeee
匹配).*
(與任何字符串匹配)foo.*
(與以foo
開始的任何字符串相匹配)ac
行與正則表達(dá)式ab*c
相匹配,因為星號也允許前面的表達(dá)式b
出現(xiàn)零次。請注意解釋*
正則表達(dá)式元字符所用的方法與解釋* glob
字符的方法根本不同。
行的開始和結(jié)束
我們在這里要詳細(xì)描述的最后幾個元字符是 ^
和 $
元字符,它們用來分別與行的開始和結(jié)束相匹配。通過在正則表達(dá)式開始處使用一個 ^ ,您可以將您的模式“錨定”在行的開始。
在下面的示例中,我們使用 ^# 正則表達(dá)式來與以 # 字符開始的任何行相匹配:
$ grep ^# /etc/fstab # /etc/fstab: static file system information. #
完整行正則表達(dá)式
可以組合 ^
和 $
來與完整的行相匹配。
例如,下面的正則表達(dá)式將與以 #
字符開始并以.
字符結(jié)束的行相匹配,在其中間可以有任意多個其它字符:
$ grep '^#.*/.$' /etc/fstab # /etc/fstab: static file system information.
在上面的示例中,我們用單引號將我們的正則表達(dá)式括起來以阻止 shell
解釋 $
。
在不使用單引號的情況下,grep
甚至沒有機(jī)會查看 $
,$
就從我們的正則表達(dá)式上消失了。
正則總結(jié)
元字符
.
:小數(shù)點(diǎn)可以匹配除\n
以外的任意一個字符。如果要匹配包括\n
在內(nèi)的所有字符,一般用[\s\S]
,或者是用.
加(?s)
匹配模式來實現(xiàn)。[abc]
:匹配方括號中的任意一個字符。可以使用-表示字符范圍,如[a-z0-9]
匹配小寫字母和阿拉伯?dāng)?shù)字。[^abc]
:在方括號內(nèi)開頭使用^
符號,表示匹配除方括號中字符之外的任意字符。|
: 表示或\d
匹配阿拉伯?dāng)?shù)字,等同于[0-9]
。\D
匹配阿拉伯?dāng)?shù)字之外的任意字符,等同于[^0-9]
。\x
匹配十六進(jìn)制數(shù)字,等同于[0-9A-Fa-f]
。\X
匹配十六進(jìn)制數(shù)字,等同于[^0-9A-Fa-f]
。\w
匹配單詞字母,等同于[0-9A-Za-z_]
。\W
匹配單詞字母之外的任意字符,等同于[^0-9A-Za-z_]
。\t
匹配<TAB>
字符。\s
匹配空白字符,等同于[ /t]
。\S
匹配非空白字符,等同于[^ /t]
。\a
所有的字母字符. 等同于[a-zA-Z]
\l
小寫字母[a-z]
\L
非小寫字母[^a-z]
\u
大寫字母[A-Z]
\U
非大寫字母[^A-Z]
表示數(shù)量的元字符
元字符 說明
*
匹配0-任意個
\+
匹配1-任意個
\?
匹配0-1個
\{n,m\}
匹配n-m個
\{n\}
匹配n個
\{n,\}
匹配n-任意個
\{,m\}
匹配0-m個
換行符 說明
\r,\n
回車和換行\\
匹配\
\^
,\$
,\.
匹配^
$
.
以下字符在匹配其本身時,通常需要進(jìn)行轉(zhuǎn)義。
在實際應(yīng)用中,根據(jù)具體情況,需要轉(zhuǎn)義的字符可能不止如下所列字符 : $
^
{
[
(
|
)
*
+
?
\
表示位置的符號
$
匹配行尾^
匹配行首\<
匹配單詞詞首\>
匹配單詞詞尾\b
匹配單詞邊界
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
linux最快的文本搜索神器ripgrep(grep的最好代替者)
這篇文章主要介紹了linux最快的文本搜索神器ripgrep(grep的最好代替者),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11解決Ubuntu 16.04下提示boot分區(qū)空間不足的辦法
最近看了看/boot的大小,發(fā)現(xiàn)幾次升級后,大小不足,所以想擴(kuò)容,一開始還想用磁盤操作,但上網(wǎng)查詢后發(fā)現(xiàn),磁盤操作實在風(fēng)險太大,特別是雙系統(tǒng)的Linux,操作又是很麻煩,后來發(fā)現(xiàn)可以刪除多余的舊內(nèi)核來清理/boot,釋放空間。下面來看看詳細(xì)的解決方法吧。2017-02-02解決ubuntu安裝軟件時,status-code=409報錯的問題
這篇文章主要介紹了解決ubuntu安裝軟件時,status-code=409報錯的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12apache在win2003下的安全設(shè)置(配合文件夾權(quán)限目錄,很好很安全)
眾所周知,在windows下當(dāng)Apache第 一次被安裝為服務(wù)后,它會以用戶“System”(本地系統(tǒng)賬號)運(yùn)行。如果web服務(wù)器的所有資源都在本地系統(tǒng)上,這樣做會問題比較少,但是將會具有很 大的安全 權(quán)限來影響本地機(jī)器,因此千萬不能開啟System帳號的網(wǎng)絡(luò)權(quán)限2012-01-01Linux下Python腳本自啟動和定時啟動的詳細(xì)步驟
這篇文章主要介紹了Linux下Python腳本自啟動和定時啟動的詳細(xì)步驟,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2019-09-09linux 程序、動態(tài)庫、靜態(tài)庫內(nèi)部添加版本號和編譯時間詳解
下面小編就為大家?guī)硪黄猯inux 程序、動態(tài)庫、靜態(tài)庫內(nèi)部添加版本號和編譯時間詳解。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12apache實現(xiàn)部署多個網(wǎng)站(一個ip部署多域名)的方法詳解
最近去機(jī)房幫別人配置網(wǎng)站,機(jī)房的服務(wù)器本身已經(jīng)搭建了一個網(wǎng)站,我們需要再配置一個,所以記錄下來,這篇文章主要給大家介紹了關(guān)于apache如何實現(xiàn)部署多個網(wǎng)站(一個ip部署多域名)的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。2017-11-11