Regular Expression与grep

關鍵是要能夠區分 shell command line 上的 meta 與 literal 這兩種不同的字符類別.
然後, 我這裡才跟你講:
--- RE 表達式裡的字符也是分為 meta 與 literal 這兩種!
呵, 不知親愛的讀者是否被我搞混亂了呢? ...  ^_^
這也難怪啦, 因為這的確是最容易混亂的地方, 剛學 RE 的朋友很多時候都死在這裡!
因此請特別小心理解哦...
簡單而言, 除非你將 RE 寫在特定程式使用的腳本裡,
否則, 我們的 RE 也是透過 command line 輸入的.
然而, 不少 RE 所始用的 meta 字符, 跟 shell meta 字符是衝突的.
比方說, * 這個字符, 在 RE 裡是一個 modifier(後述), 在 command line 上, 卻是個 wildcard !

那麼, 我們該如何解決這樣的衝突呢? 關鍵就是看你對十三問第 4 問所提的 quoting 是否夠理解了!
若你明白到 shell quoting 就是在 command line 上關閉 shell meta 這一基本原理,
那你就能很輕鬆的解決 RE meta 與 shell meta 的衝突問題了:
--- 用 shell quoting 關掉 shell meta 就是了!
就這麼簡單...  ^_^
再以剛提到的 * 字符為例, 若在 command line 中沒有 quoting 處理的話, 如 abc* ,
那就會被作為 wildcard expansion 來擴充及重組了.

若將之置於 quoting 中, 如 "abc*", 則可避免 wildcard expansion 的處理.


當我們在談到 RE 時, 千萬別跟 wildcard 搞混在一起!
尤其在 command line 的位置裡, wildcard 只作用於 argument 的 path 上.
但是 RE 卻只用於"字串處理"的程式之中, 這與路逕名稱一點關系也沒有!

RE 所處理的字串通常是指純文檔或透過 stdin 讀進的內容...

在RE的表达式里,主要分两种字符(character):literal 与 meta。

literal:就是在RE里不具特殊功能的字符,如 abc,123 这些;

meta在RE里具有特殊的功能,要开关之,需要在meta 前面使用 escape(\)字符。


字符组合(character set)就是将多个连续的字符作一个集合,比方说:

abc:表示abc三个连续的字符,但批次独立而非集合。(可简单视为三个char. set)

(abc):表示abc这三个连续字符的集合。(可简单视为一个char. set)

abc|xyz:表示或abc或xyz这两个char set之一。

[abc]:表示单一字符,可为a或b或c。(与wildcard值[abc]原理相同)

[^abc]:表示单一字符,不为a或b或c即可。(与wildcard之[!abc]原理相同)

[]abc]:表示单一字符,可为]或a或b或c。]必须放第一个。

[abc-]:表示单一字符,可为a或b或c或-。-必须放在最后一个。

[a^bc]:表示单一字符,可为a或^或b或c。^不能放在第一个。

.:表示任意单一字符。(与wildcard之?原理相同)


RE中常见的meta字符:

——锚点(anchor)

用以标识RE于句子中的位置所在。常见有:

^:表示句首。如^abc表示以abc開首的句子。(以换行符为标记)

$:表示句尾。如abc$表示以abc结尾的句子。(以换行符为标记)

\<:表示词首。如\<abc表示以abc開首的词。

\>:表示词尾。如abc\>表示abc结尾的词。


——修饰字符(modifier)

独立表示时本身不具意义,专门用以修改前一个char. set的出现次数。常见的有:

*:表示前一个char. set 的出现次数为0或多次。如ab*c表示a与c之间可有0或多个b存在。

?:表示前一个char. set的出现次数为0或1次。如ab?c表示a与c之间可有0或1个b存在。

+:表示前一个char. set 的出现次数为1或多次。如ab+c表示a与c之间可有1或多个b存在。

{n}:表示前一个char. set 的出现次数必须为n次。如ab{3}c表示a与c之间必须有3个b存在。

{n,}:表示前一个char. set 的出现次数至少为n次。如ab{3,}c表示a与c之间至少有3个b存在。

{n,m}:表示前一个char. set 的出现次数为n到m次。如ab{3,5}c表示a与c之间有3到5个b存在。


然而, 當我們在識別 modifier 時, 卻很容易忽略"邊界(boundary)"字符的重要性.
以剛提到的 ab{3,5}c 為例, 這裡的 a 與 c 就是邊界字符了.
若沒有邊界字符的幫忙, 我們很容以作出錯誤的解讀.
比方說: 我們用 ab{3,5} 這個 RE (少了 c 這個邊界字符)可以抓到 abbbbbbbbbbc (a 後有 10 個 b )這串字嗎?
從剛才的 modifier 我們一般會認為我們要的 b 是 3 到 5 個, 若超出了此範圍, 就不是我們要表達的.
因此, 我們或會很輕率的認為這個 RE 抓不到結果(上述“abbbbbbbbbbc”字串)...
然而答案卻是可以的! 為甚麼呢?
讓我們重新解讀 ab{3,5} 這個 RE 看看:
我們要表達的是 a 後接 3 到 5 個 b 即可, 但 3 到 5 個 b 後面我們卻沒規定是甚麼,
因此在 RE 後面可以是任意的文字, 當然包括 b 也可以啦! (明白了嗎?)
同樣的, 我們用 b{3,5}c 也同樣可以抓到 abbbbbbbbbbc 這串字的.
但我們若使用 ab{3,5}c 這樣的 RE 時, 由於同時有 a 與 c 這兩個邊界字符, 那就截然不同了!


比方以 grep 來說, 在 Linux 上你可找到 grep, egrep, fgrep 這幾個程式, 其差異大致如下:

* grep:
傳統的 grep 程式, 在沒有參數的情況下, 只輸出符合 RE 字串之句子. 常見參數如下:
-v: 逆反模示, 只輸出"不含" RE 字串之句子.
-r: 遞迴模式, 可同時處理所有層級子目錄裡的文件.
-q: 靜默模式, 不輸出任何結果(stderr 除外. 常用以獲取 return value, 符合為 true, 否則為 false .)
-i: 忽略大小寫.
-w: 整詞比對, 類似 \<word\> .
-n: 同時輸出行號.
-c: 只輸出符合比對的行數.
-l: 只輸出符合比對的文件名稱.

-h:查询多文件时 不显示文件名。

-s:不显示不存在或无匹配文件的错误信息。

-v:显示不包含匹配文件的所有行。

-o: 只輸出符合 RE 的字串. (gnu 新版獨有, 不見得所有版本都支持.)
-E: 切換為 egrep .

* egrep:
為 grep 的擴充版本, 改良了許多傳統 grep 不能或不便的操作. 比方說:
- grep 之下不支持 ? 與 + 這兩種 modifier, 但 egrep 則可.
- grep 不支持 a|b 或 (abc|xyz) 這類"或一"比對, 但 egrep 則可.
- grep 在處理 {n,m} 時, 需用 \{ 與 \} 處理, 但 egrep 則不需.

egrep的一个显著特性是可以以一个文件作为保存的字符串,然后降至传给egrep作为参数,为此使用-f开关。

諸如此類的... 我個人會建議能用 egrep 就不用 grep 啦...  ^_^

* fgrep:
不作 RE 處理, 表達式僅作一般字串處理, 所有 meta 均失去功能.


grep一般格式为:

grep [选项]基本正则表达式[文件]
这里基本正则表达式可为字符串。

单引号双引号

在grep命令中输入字符串参数时,最好将其用双引号括起来。

在调用模式匹配时,应使用单引号。


1、类名

grep允许使用国际字符模式匹配或匹配模式的类名形式。

类名及其等价的正则表达式类

[[:upper:]] [A-Z]
[[:alnum:]] [0-9a-zA-Z]
[[:lower:]] [a-z]
[[:space:]] 空格或tab键
[[:digit:]] [0-9] 
[[:alpha:]] [a-zA-Z]


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值