<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ##shell十三問之15: [^ ] 跟[! ]差在哪? (RE: Regular Expression) ------------------------------------------------------------ ### Part-II Regular Expression (正則表達式) ------------------------------------------ 接下來的Regular Expression(RE) 可是個大題目,要講的很多。 我這里當然不可能講得很全。 只希望能帶給大家一個基本的入門概念,就很足夠了... 先來考一下英文好了:What is expression? 簡單來說,就是"表達",也就是人們在溝通的時候所要陳述的內容。 然而,生活中,表達方要清楚的將意思描述清楚, 而讓接收方完整無誤地領會,可不是件容易的事情。 因而才會出現那么多的"誤會", 真可嘆句"表達不易"啊...... 同樣的情形也發生在計算機的數據處理過程中, 尤其是當我們在描述一段"文字內容"的時候.... 那么,我們不禁要問: 有何方法可以讓大家的誤會降至最低程度, 而讓表達的精確度達到最高程度呢? 答案就是"標準化"了, 也就是我們這里要談的`Regular Expression`啦...^_^ 然而,在進入`RE`介紹之前,不妨先讓我們溫習一下shell十三問之第4問, 那就是關于quoting的部分。 **關鍵是要能夠區分 shell command line上的meta與literal的這兩種不同的字符類型**。 然后,我這里也跟你講: **RE 表達式里字符也分meta與literal這兩種**。 呵,不知親愛的讀者是否被我搞混亂了呢?... ^_^ 這也難怪啦,因為這的確是最容易混淆的地方, 剛學`RE`的朋友很多時候,都死在這里! 因此,請特別小心理解哦... 簡單而言,除非你將`RE`寫在特定程序使用的腳本里, 否則,我們的`RE`也是通過 command line輸入的。 然而, **不少RE所使用的meta字符,跟shell 的meta字符是沖突的**。 比方說, **`*`這個字符,在RE里是一個modifier(修飾符);而在command line上,確是wildcard(通配符)**。 那么,我們該如何解決這樣的沖突呢? 關鍵就是看你對shell十三問的第4問中所提的quoting是否足夠理解了! 若你明白到 **shell quoting 就是用來在command line上關閉shell meta這一基本原理**, 那你就能很輕松的解決 RE meta與shell meta的沖突問題了: **用shell quoting 關閉掉shell meta就是了**。 就這么簡單... ^_^ 再以剛提到`*`字符為例, 若在command line的path中沒有quoting處理的話, 如abc\* 就會被作為wildcard expression來擴充及重組了。 若將其置于quoting中,即"abc\*",則可以避免wildcard expand的處理。 好了,說了大半天,還沒有進入正式的RE介紹呢.... 大家別急,因為我的教學風格就是要先建立基礎,循序漸進的... ^_^ 因此, 我這里還要再啰嗦一個觀念,才會到RE的說明啦...(哈...別打我...) 當我們在談到RE時,千萬別跟wildcard搞混在一起! 尤其是 ``` 在command line的位置里,wildcard只作用于argument的path上; 而RE卻只用于"字符串處理" 的程序中,這與路徑名一點關系也沒有。 ``` > **Tips:** > RE 所處理的字符串,通常是指純文本或通過stdin讀進的內容。 okay,夠了夠了,我已看到一堆人開始出現不耐煩的樣子了... ^_^ 現在,就讓我們登堂入室,揭開RE的神秘面紗吧, 這樣可以放過我了吧? 哈哈... 在RE的表達式里,主要分為兩種字符:`literal`與`meta`。 所謂`literal`就是在RE里不具有特殊功能的字符,如abc,123等; 而`meta`,在RE里具有特殊的功能。 要關閉之,需要在`meta`之前使用escape(\)轉義字符。 然而,在介紹`meta`之前,先讓我們來認識一下字符組合(character set)會更好些。 一、所謂的char set就是將多個連續的字符作為一個集合。 例如: | char 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]原理相同)| | . | 表示任意單個字符,(與wildcard的?原理相同)| note: abc|xyz 表示abc或xyz這兩個char set之一 在認識了RE的char set這個概念之后,然后,在讓我們多認識幾個RE中常見的meta字符: 二、 錨點(anchor): 用以標識RE在句子中的位置所在。 常見的有: |錨點 | 說明| |-------|-------| | ^ | 表示句首。如,^abc表示以abc開頭的句子。| | $ | 表示句尾。如,abc$表示以abc結尾的句子。| | \\< | 表示詞首。如,\\<abc表示以abc開頭的詞。| | \\> | 表示詞尾。如,abc\\>表示以abc結尾的詞。| 三、 修飾符(modifier):獨立表示時本身不具意義,專門用以修飾前一個char set出現的次數。 常見的有: | modifier | 說明| |------------|----------------------------------- | * | 表示前一個char set出現0次或多次,即任意次。如ab*c表示a與c之間可以有0個或多個b。| | ? | 表示前一個char set出現0次或1次,即至多出現1次。如ab?c 表示a與c之間可以有0個或1個b。| | + | 表示前一個char set出現1次或多次,即至少出現1次。如ab+c 表示a與c之間可以有1個或多個b。| | {n} | 表示前一個char set出現n次。如ab{n}c 表示a與c之間可以有n個b。| | {n, } | 表示前一個char set至少出現n次。如ab{n}c 表示a與c之間至少有n個b。| | {n, m} | 表示前一個char set至少出現n次,至多出現m次。如ab{n,m}c 表示a與c之間至少有n個b,至多有m個b。| 然而,當我們在識別modifier時,卻很容易忽略"邊界(boundary)字符"的重要性。 以`ab{3,5}c`為例,這里的a與c就是邊界字符了。 若沒有邊界字符的幫忙,我們很容易做出錯誤的解讀。 比方說: 我們用`ab{3,5}`這個RE(少了c這個邊界字符) 可以抓到"abbbbbbbbbb"(a后面有10個b)的字符串嗎? 從剛才的modifier的說明,我們一般認為,我們要的b是3到5個, 若超出了此范圍,就不是我們所要表達的。 因此,我們或許會很輕率地認為這個RE抓不到結果(上述"abbbbbbbbbb"字符串)。 然而,答案卻是可以的!為什么呢? 讓我們重新解讀`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這連個邊界字符,就截然不同了! 有空在思考一下,為何我們用下面這些RE都抓到abc這樣的字符串呢? ``` x* ax*, abx*, ax*b abcx*, abx*c, ax*bc bx*c, bcx*, x*bc ``` 但, 若我們在這些RE前后分別加`^`與`$`這樣的anchor,那又如何呢? 剛學RE時,只要能掌握上面這些基本的meta的大概就可以入門了。 一如前述,RE是一種規范化的文字表達式, 主要用于某些文字處理工具之間,如: grep, perl, vi,awk,sed,等等, 常用于表示一段連續的字符串,查找和替換。 然而每種工具對RE表達式的具體解讀或有一些細微差別, 不過節本原理還是一致的。 只要掌握RE的基本原理,那就一理通百理了, 只是在實踐時,稍加變通即可。 比方以grep來說, 在Linux上,你可以找到grep,egrep,fgrep這些程序, 其差異大致如下: grep: 傳統的grep程序,在沒有任何選項(options)的情況下,只輸出符合RE字串的句子, 其常見的選項如下: | 選項 (option)| 用途| | -----|---------------------------- | -v | 反模式, 只輸出“不含”RE的字符串的行。| | -r | 遞歸模式,可同時處理所有層級的子目錄里的文件| | -q | 靜默模式,不輸出任何結果(stderr 除外,常用于獲取return value,符合為true,否則,為false.| | -i | 忽略大小寫| | -w | 整詞匹配,類似 \<RE\>| | -n | 同時輸出行號| | -l | 輸出匹配RE的文件名| | -o | 只輸出匹配RE的字符串。(gnu新版獨有,不見得所有版本支持)| | -E | 切換為egrep| egrep:為grep的擴充版本,改良了許多傳統grep不能或者不便的操作, - grep下不支持`?`與`+`這兩種meta,但egrep支持; - grep 不支持`a|b`或(`abc|xyz`)這類“或一”的匹配,但egrep支持; - grep 在處理`{n,m}`時,需要\\{ 與 \\}處理,但egrep不需。 等諸如此類的。我個人建議能用egrep就不用grep啦...^_^ fgrep: 不作RE處理,表達式僅作一般的字符串處理,所有的meta均市區功能。 好了,關于RE的入門,我們暫時就介紹到這里。 雖然有點亂,且有些觀念也不恨精確, 不過,姑且算是對大家的一個交差吧...^_^ 若這兩天有時間的話,我在舉些范例來分析一下,以幫助大家更好的理解。 假如更有可能的話,也順道為大家介紹一下sed這個工具。 --------------------------------------- ### Part-III eval --------------------------------------- 講到command line的重組特性, 真的需要我們好好的加以解釋的。 如此便能抽絲剝繭的一層層的將整個command line分析的 一清二楚,而不至于含糊。 假如這個重組的特性理解了,那我們介紹一個好玩的命令:`eval`. 我們在變量替換的過程中,常會碰到所謂的復式變量的問題: 如: ```shell a=1 A1=abc ``` 我們都知道`echo $A1`就可以得到abc的結果。 然而,我們能否用$A$a來取代$A1,而同一樣替換為abc呢? 這個問題我們可用很輕松的用`eval`來解決: ```shell eval echo \$A$a ``` 說穿了,`eval` 只不過是在命令行完成替換重組后, 在來一次替換重組罷了... 就是這么簡單啦~~~ ^_^
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看