歡迎光臨
每天分享高質量文章

Shell 中的命令替換及引數擴充套件 | Linux 中國

今天和大家分享的主要是 “命令替換” 以及 “引數擴充套件” 。
— 季文康


本文導航
轉載自 | http://www.cnblogs.com/itxdm/p/something_of_shellscirpt.html
 作者 | 季文康

前言

其實,你現在閱讀到的是第三版的文章(幾乎全部重構)。記得我寫第一版的時候,還是一名 “參賽選手”。後來比賽失利便和朋友一起做 IDC 創業。第二次改的時候,是我發現閱讀量在倆三個月內直接自己站點 top 到第一,加上參與了開源社群,維護了 LCTT-CLI 專案。最後第三次也就是這次,是因為透過了 RHCE 模擬考加上一年多積累。所以這次的內容或是排版都應是最棒!BTW:這篇文章在我的部落格IT兄弟盟[2],依舊是第一的閱讀量!

一開始寫這篇文章是因為兼職創業 IDC 公司運維,需要一點 shell script 來實現某些需求。雖然現在已經是 Python 的時代了。插個話題,我怎麼理解 Python 和 Shell 呢?拿游泳來做個比喻:前者是正規游泳館,有正規教練輔助相伴;後者是鄉下小湖泊,麻雀雖小五臟俱全。人工智慧選中的 Python 勢必鋒不可當,經典的 Shell 也相當精妙絕倫。比如以前我寫 Shell 的時候用了很多 if else 陳述句、 case 陳述句,有 test 陳述句,懂得 || && ; 輔助,這是最小白的。後面學習了很多比較運運算元,但多數還是在積累命令數量以及條件陳述句。再到現在,我開始去思考命令和命令之間存在的關係、陳述句分隔符的意義、BASH 控制結構等等。

所以今天和大家分享的主要是 “命令替換” 以及 “引數擴充套件” 。

什麼是命令替換

簡單的來說就是在 SHELL 內巢狀多條命令,一次性執行得到結果。

1、一層 SHELL 巢狀

  1. # echo `whoami`

  2. # echo $(whoami)

  3. # echo "hello,`whoami`"

  4. # echo "hello,$(whoami)"

2、二層 SHELL 巢狀

  1. # echo `cat ./gn2.txt` | sed -s "s;$; --list;"

使用 ``讀取檔案內容,再使用管道符二次處理後。執行!

註意:這裡已經用了一層巢狀,以下多個小節會套用以實現二層巢狀。

a. 使用 "$()" 進行二層巢狀

b. 使用 "|" 進行命令導向

c. 註意事項以及解答一些疑問

可能有讀者已經註意到了,之前在簡單 SHELL 一層巢狀中說了巢狀還有另一種。那為什麼不使用 ` ` 進行巢狀。

◈ 根本的原因是:` ` 不支援命令巢狀執行!

◈ 強制執行。也只能認出第一組,其餘按照空格作為間隔各個執行 或 按照管道符(含)直到末尾執行。
◈ 比較陳舊。容易與“單引號”混淆。

◈ 它是美式鍵盤左上角 ESC 下麵的包含 ~ 的反引號鍵!
◈ 已有替代品。$(...) 格式受到POSIX標準支援,也利於巢狀。

◈ $() 可以多層巢狀類似 $($($())) ,但如果內部有一個` ` 也是可以執行的喲(出於相容考慮)!

3、進階

之前我們介紹了 `` 和 $(...) ,這倆種命令執行。

想來現在你一定對命令執行有比較深的理解了。現在,我們需要再進階一下~

1、 (cmd) 與 {var}

關於 ( ) 與 { },和 命令替換 一樣都是 shell 擴充套件 父類下的相關概念。

提示:{} 頭部大括號右側必須有一個空格,尾部括號左側必須有分號結尾。

  1. # ( echo firest;echo second; )

  2. # { echo third;echo fourth; }

註意: ( ) 只是對一串命令重新開一個 子 shell 進行執行, { } 對一串命令在 當前 shell 執行。

2、() 與 {} 造成的影響

a. () 括號內的陳述句影響在括號內

  1. # var=source

  2. # ( echo $var;var=global;echo $var; )

  3. # echo $var

b. {} 括號內的陳述句影響到全域性。

  1. # echo $var

  2. # { echo $var;var=global;echo $var; }

  3. # echo $var

註意:{} 改變 var 的變數以後,外部也受到了影響。

什麼是引數擴充套件

引數擴充套件的基本格式是 ${ parameter },擴充套件的結果是 ${ parameter }被替換為相應的值。

1、實體一

  1. echo $1 $11

  2. echo $1 ${11}

首先解釋下 ${1..9} 是什麼意思。在我們寫 Shell 時必不可免的需要傳遞引數以實現自定義變數。當超過阿拉伯數字 9 以後。就需要使用 ${ parameter } 明確告訴Shell第 11 個引數是 ${11}

提示:上圖顯示 101 就是因為 $11 不滿足 [1-9]{1} 。系統將 11 拆分成 $1 和 1 ,所以運算後結果是 101

2、實體二

  1. ban=ban

  2. echo a $banana

  3. echo a ${ban}ana

這個實體中,我想輸出 banana 。已經定義了一個 ban 的變數為 ban ,只要加上 ana 就可以成為 “笨啦啦”。

但是很顯然的不加 {} 是無法做到使變數 $ban 配合 ana 顯示出 banana 的!

什麼是變數擴充套件

從官方定義上來說,我並不應該將 “變數擴充套件” 無中生有出來。

$ 字元引入引數擴充套件,命令替換或算術擴充套件。" —— 官方手冊

主要是出於倆個方面考慮:

◈ 多數接受。國內出現了大量 ”變數擴充套件“ 的文章,多數人已經接受這個名稱。
◈ 便於理解。引數就是 ${...} 括號內的東西,而變數一詞可表示所有操作圍繞變數展開。
◈ 便於記錄。切分以後,對寫這篇文章的排版有幫助。亦可以從基礎、中級、高階有一定水平劃分。

實體:

  1. var='This is one test sentence.'

  2. var1=parameter

  3. var2=word

現在我們有了這樣的一個句子,我希望做一些判斷、摘取(或者說:切片)或修改。我該如何操作?

1、變數替換

a. ${parameter:-word}

  1. # echo ${var1:-$var2}

  2. parameter

  3. # var1=

  4. # echo ${var1:-$var2}

  5. word

如果 var1 未設定或為空,則替換成 var2

b. ${parameter:=word}

同上。位置引數和特殊引數不能以這種方式分配。

c. ${parameter:?word}

  1. # var1=

  2. # echo ${var1😕var2}

  3. bash: var1: var2

  4. # echo $?

  5. 1

當變數 var1 未設定或為空,shell 也是可互動時,進行報錯並且退出。如果 shell 不可互動,則發生變數替換。

d. ${parameter:+word}

  1. # echo $var1

  2. parameter

  3. # echo $var2

  4. word

  5. # echo ${var1:+$var2}

  6. word

  7. # echo $var1

  8. parameter

如果 var1 為空或未設定,那麼就什麼都不做。不然使用 var2 進行替換。

提示: 在我測試的時候,我發現並不是全域性生效的。

2、變數切片

a. 範圍切片(同方向)

  1. # echo ${var:8:17}

  2. one test sentence

註意:倆個數字都是從頭開始數的。

b. 範圍切片(非同向)

  1. # echo ${var:8:-1}

  2. one test sentence

  3. # echo ${var:8:(-1)}

  4. one test sentence

提示:倆種寫法都是正確的。

c. 切片位置

  1. # a='This is one'

  2. # echo ${#a}

  3. 11

提示 :首先建立變數 a='This is one' ,然後使用 echo ${#a} 將字元數量讀了出來。

3、變數修改

a. 簡單修改

  1. # echo ${var}

  2. This is one test sentence.

  3. # echo ${var/one/a}

  4. This is a test sentence.

提示:個人認為這種是最好的方式了,可以範圍式修改(包含刪除)。

b. 簡單刪除

  1. # echo ${var%sentence.}

  2. This is one test

  1. # echo ${var#This is}

  2. one test sentence.

c. 附:表格

< 如顯示不全,請左右滑動 >
變數設定方式 說明
${變數#關鍵字} 若變數內容從開始的資料符合“關鍵字”,則將符合的最資料刪除
${變數##關鍵字} 若變數內容從開始的資料符合“關鍵字”,則將符合的最資料刪除
${變數%關鍵字} 若變數內容從開始的資料符合“關鍵字”,則將符合的最資料刪除
${變數%%關鍵字} 若變數內容從開始的資料符合“關鍵字”,則將符合的最資料刪除
${變數/舊字串/新字串} 若變數內容符合“舊字串”,則首個舊字元會被新字元替換
${變數/舊字串//新字串} 若變數內容符合“舊字串”,則全部舊字元會被新字元替換

更深入學習,探索資料

◈ Bash 實體,第二部分[3]
◈ Bash 參考手冊:Bash Reference Manual[4]
◈ Shell-Expansions 章節:Shell-Expansions[5]
◈ Shell Parameter Expansion 章節 Shell Parameter Expansion[6]

推薦文章

< 左右滑動檢視相關文章 >

點選圖片、輸入文章 ID 或識別二維碼直達

贊(0)

分享創造快樂