zoukankan      html  css  js  c++  java
  • 變數內容的刪除、取代與替換 (Optional)

    變數內容的刪除、取代與替換 (Optional)

    變數除了可以直接設定來修改原本的內容之外,有沒有辦法透過簡單的動作來將變數的內容進行微調呢? 舉例來說,進行變數內容的刪除、取代與替換等!是可以的!我們可以透過幾個簡單的小步驟來進行變數內容的微調喔! 底下就來試試看!

    • 變數內容的刪除與取代

    變數的內容可以很簡單的透過幾個咚咚來進行刪除喔!我們使用 PATH 這個變數的內容來做測試好了。 請你依序進行底下的幾個例子來玩玩,比較容易感受的到鳥哥在這裡想要表達的意義:

    範例一:先讓小寫的 path 自訂變數設定的與 PATH 內容相同
    [dmtsai@study ~]$ path=${PATH}
    [dmtsai@study ~]$ echo ${path}
    /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
    
    範例二:假設我不喜歡 local/bin,所以要將前 1 個目錄刪除掉,如何顯示?
    [dmtsai@study ~]$ echo ${path#/*local/bin:}
    /usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
    

    上面這個範例很有趣的!他的重點可以用底下這張表格來說明:

    ${variable#/*local/bin:}
       上面的特殊字體部分是關鍵字!用在這種刪除模式所必須存在的
    
    ${variable#/*local/bin:}
       這就是原本的變數名稱,以上面範例二來說,這裡就填寫 path 這個『變數名稱』啦!
    
    ${variable#/*local/bin:}
       這是重點!代表『從變數內容的最前面開始向右刪除』,且僅刪除最短的那個
    
    ${variable#/*local/bin:}
       代表要被刪除的部分,由於 # 代表由前面開始刪除,所以這裡便由開始的 / 寫起。
       需要注意的是,我們還可以透過萬用字元 * 來取代 0 到無窮多個任意字元
    
       以上面範例二的結果來看, path 這個變數被刪除的內容如下所示:
    /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
    

    很有趣吧!這樣瞭解了 # 的功能了嗎?接下來讓我們來看看底下的範例三!

    範例三:我想要刪除前面所有的目錄,僅保留最後一個目錄
    [dmtsai@study ~]$ echo ${path#/*:}
    /usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
    # 由於一個 # 僅刪除掉最短的那個,因此他刪除的情況可以用底下的刪除線來看:
    # /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
    
    [dmtsai@study ~]$ echo ${path##/*:}
    /home/dmtsai/bin
    # 嘿!多加了一個 # 變成 ## 之後,他變成『刪除掉最長的那個資料』!亦即是:
    # /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
    

    非常有趣!不是嗎?因為在 PATH 這個變數的內容中,每個目錄都是以冒號『:』隔開的, 所以要從頭刪除掉目錄就是介於斜線 (/) 到冒號 (:) 之間的資料!但是 PATH 中不止一個冒號 (:) 啊! 所以 # 與 ## 就分別代表:

    • # :符合取代文字的『最短的』那一個;
    • ##:符合取代文字的『最長的』那一個

    上面談到的是『從前面開始刪除變數內容』,那麼如果想要『從後面向前刪除變數內容』呢? 這個時候就得使用百分比 (%) 符號了!來看看範例四怎麼做吧!

    範例四:我想要刪除最後面那個目錄,亦即從 : 到 bin 為止的字串
    [dmtsai@study ~]$ echo ${path%:*bin}
    /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin
    # 注意啊!最後面一個目錄不見去!
    # 這個 % 符號代表由最後面開始向前刪除!所以上面得到的結果其實是來自如下:
    # /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
    
    範例五:那如果我只想要保留第一個目錄呢?
    [dmtsai@study ~]$ echo ${path%%:*bin}
    /usr/local/bin
    # 同樣的, %% 代表的則是最長的符合字串,所以結果其實是來自如下:
    # /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
    

    由於我是想要由變數內容的後面向前面刪除,而我這個變數內容最後面的結尾是『/home/dmtsai/bin』, 所以你可以看到上面我刪除的資料最終一定是『bin』,亦即是『:*bin』那個 * 代表萬用字元! 至於 % 與 %% 的意義其實與 # 及 ## 類似!這樣理解否?

    例題:
    假設你是 dmtsai ,那你的 MAIL 變數應該是 /var/spool/mail/dmtsai 。假設你只想要保留最後面那個檔名 (dmtsai), 前面的目錄名稱都不要了,如何利用 $MAIL 變數來達成?
    答:
    題意其實是這樣『/var/spool/mail/dmtsai』,亦即刪除掉兩條斜線間的所有資料(最長符合)。 這個時候你就可以這樣做即可:
    [dmtsai@study ~]$ echo ${MAIL##/*/}
    
    相反的,如果你只想要拿掉檔名,保留目錄的名稱,亦即是『/var/spool/mail/dmtsai』 (最短符合)。但假設你並不知道結尾的字母為何,此時你可以利用萬用字元來處理即可,如下所示:
    [dmtsai@study ~]$ echo ${MAIL%/*}
    

    瞭解了刪除功能後,接下來談談取代吧!繼續玩玩範例六囉!

    範例六:將 path 的變數內容內的 sbin 取代成大寫 SBIN:
    [dmtsai@study ~]$ echo ${path/sbin/SBIN}
    /usr/local/bin:/usr/bin:/usr/local/SBIN:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
    # 這個部分就容易理解的多了!關鍵字在於那兩個斜線,兩斜線中間的是舊字串
    # 後面的是新字串,所以結果就會出現如上述的特殊字體部分囉!
    
    [dmtsai@study ~]$ echo ${path//sbin/SBIN}
    /usr/local/bin:/usr/bin:/usr/local/SBIN:/usr/SBIN:/home/dmtsai/.local/bin:/home/dmtsai/bin
    # 如果是兩條斜線,那麼就變成所有符合的內容都會被取代喔!
    

    我們將這部份作個總結說明一下:

    變數設定方式 說明
    ${變數#關鍵字}
    ${變數##關鍵字}
    若變數內容從頭開始的資料符合『關鍵字』,則將符合的最短資料刪除
    若變數內容從頭開始的資料符合『關鍵字』,則將符合的最長資料刪除
    ${變數%關鍵字}
    ${變數%%關鍵字}
    若變數內容從尾向前的資料符合『關鍵字』,則將符合的最短資料刪除
    若變數內容從尾向前的資料符合『關鍵字』,則將符合的最長資料刪除
    ${變數/舊字串/新字串}
    ${變數//舊字串/新字串}
    若變數內容符合『舊字串』則『第一個舊字串會被新字串取代』
    若變數內容符合『舊字串』則『全部的舊字串會被新字串取代』
    • 變數的測試與內容替換

    在某些時刻我們常常需要『判斷』某個變數是否存在,若變數存在則使用既有的設定,若變數不存在則給予一個常用的設定。 我們舉底下的例子來說明好了,看看能不能較容易被你所理解呢!

    範例一:測試一下是否存在 username 這個變數,若不存在則給予 username 內容為 root
    [dmtsai@study ~]$ echo ${username}
               <==由於出現空白,所以 username 可能不存在,也可能是空字串
    [dmtsai@study ~]$ username=${username-root}
    [dmtsai@study ~]$ echo ${username}
    root       <==因為 username 沒有設定,所以主動給予名為 root 的內容。
    [dmtsai@study ~]$ username="vbird tsai" <==主動設定 username 的內容
    [dmtsai@study ~]$ username=${username-root}
    [dmtsai@study ~]$ echo ${username}
    vbird tsai <==因為 username 已經設定了,所以使用舊有的設定而不以 root 取代
    

    在上面的範例中,重點在於減號『 - 』後面接的關鍵字!基本上你可以這樣理解:

    new_var=${old_var-content}
       新的變數,主要用來取代舊變數。新舊變數名稱其實常常是一樣的
    
    new_var=${old_var-content}
       這是本範例中的關鍵字部分!必須要存在的哩!
    
    new_var=${old_var-content}
       舊的變數,被測試的項目!
    
    new_var=${old_var-content}
       變數的『內容』,在本範例中,這個部分是在『給予未設定變數的內容』
    

    不過這還是有點問題!因為 username 可能已經被設定為『空字串』了!果真如此的話,那你還可以使用底下的範例來給予 username 的內容成為 root 喔!

    範例二:若 username 未設定或為空字串,則將 username 內容設定為 root
    [dmtsai@study ~]$ username=""
    [dmtsai@study ~]$ username=${username-root}
    [dmtsai@study ~]$ echo ${username}
          <==因為 username 被設定為空字串了!所以當然還是保留為空字串!
    [dmtsai@study ~]$ username=${username:-root}
    [dmtsai@study ~]$ echo ${username}
    root  <==加上『 : 』後若變數內容為空或者是未設定,都能夠以後面的內容替換!
    

    在大括號內有沒有冒號『 : 』的差別是很大的!加上冒號後,被測試的變數未被設定或者是已被設定為空字串時, 都能夠用後面的內容 (本例中是使用 root 為內容) 來替換與設定!這樣可以瞭解了嗎?除了這樣的測試之外, 還有其他的測試方法喔!鳥哥將他整理如下:

    Tips鳥哥的圖示 底下的例子當中,那個 var 與 str 為變數,我們想要針對 str 是否有設定來決定 var 的值喔! 一般來說, str: 代表『str 沒設定或為空的字串時』;至於 str 則僅為『沒有該變數』。

    變數設定方式 str 沒有設定 str 為空字串 str 已設定非為空字串
    var=${str-expr} var=expr var= var=$str
    var=${str:-expr} var=expr var=expr var=$str
    var=${str+expr} var= var=expr var=expr
    var=${str:+expr} var= var= var=expr
    var=${str=expr} str=expr
    var=expr
    str 不變
    var=
    str 不變
    var=$str
    var=${str:=expr} str=expr
    var=expr
    str=expr
    var=expr
    str 不變
    var=$str
    var=${str?expr} expr 輸出至 stderr var= var=$str
    var=${str:?expr} expr 輸出至 stderr expr 輸出至 stderr var=$str

    根據上面這張表,我們來進行幾個範例的練習吧! ^_^!首先讓我們來測試一下,如果舊變數 (str) 不存在時, 我們要給予新變數一個內容,若舊變數存在則新變數內容以舊變數來替換,結果如下:

    測試:先假設 str 不存在 (用 unset) ,然後測試一下減號 (-) 的用法:
    [dmtsai@study ~]$ unset str; var=${str-newvar}
    [dmtsai@study ~]$ echo "var=${var}, str=${str}"
    var=newvar, str=        <==因為 str 不存在,所以 var 為 newvar
    
    測試:若 str 已存在,測試一下 var 會變怎樣?:
    [dmtsai@study ~]$ str="oldvar"; var=${str-newvar}
    [dmtsai@study ~]$ echo "var=${var}, str=${str}"
    var=oldvar, str=oldvar  <==因為 str 存在,所以 var 等於 str 的內容
    

    關於減號 (-) 其實上面我們談過了!這裡的測試只是要讓你更加瞭解,這個減號的測試並不會影響到舊變數的內容。 如果你想要將舊變數內容也一起替換掉的話,那麼就使用等號 (=) 吧!

    測試:先假設 str 不存在 (用 unset) ,然後測試一下等號 (=) 的用法:
    [dmtsai@study ~]$ unset str; var=${str=newvar}
    [dmtsai@study ~]$ echo "var=${var}, str=${str}"
    var=newvar, str=newvar  <==因為 str 不存在,所以 var/str 均為 newvar
    
    測試:如果 str 已存在了,測試一下 var 會變怎樣?
    [dmtsai@study ~]$ str="oldvar"; var=${str=newvar}
    [dmtsai@study ~]$ echo "var=${var}, str=${str}"
    var=oldvar, str=oldvar  <==因為 str 存在,所以 var 等於 str 的內容
    

    那如果我只是想知道,如果舊變數不存在時,整個測試就告知我『有錯誤』,此時就能夠使用問號『 ? 』的幫忙啦! 底下這個測試練習一下先!

    測試:若 str 不存在時,則 var 的測試結果直接顯示 "無此變數"
    [dmtsai@study ~]$ unset str; var=${str?無此變數}
    -bash: str: 無此變數    <==因為 str 不存在,所以輸出錯誤訊息 
    
    測試:若 str 存在時,則 var 的內容會與 str 相同!
    [dmtsai@study ~]$ str="oldvar"; var=${str?novar}
    [dmtsai@study ~]$ echo "var=${var}, str=${str}"
    var=oldvar, str=oldvar  <==因為 str 存在,所以 var 等於 str 的內容
    

    基本上這種變數的測試也能夠透過 shell script 內的 if...then... 來處理, 不過既然 bash 有提供這麼簡單的方法來測試變數,那我們也可以多學一些嘛! 不過這種變數測試通常是在程式設計當中比較容易出現,如果這裡看不懂就先略過,未來有用到判斷變數值時,再回來看看吧! ^_^

  • 相关阅读:
    Java多线程-新特性-有返回值的线程
    Java多线程-新特性-线程池
    java多线程-慎重使用volatile关键字
    Java多线程-线程的调度(守护线程)
    Java多线程-线程的调度(合并)
    Java多线程-线程的调度(让步)
    Java多线程-线程的调度(优先级)
    Java多线程-线程的调度(休眠)
    Java多线程-线程的交互
    let 命令 与 var的区别
  • 原文地址:https://www.cnblogs.com/taosiyu/p/13085090.html
Copyright © 2011-2022 走看看