Shell 中的命令替換及引數擴充套件
前言
其實,你現在閱讀到的是第三版的文章(幾乎全部重構)。記得我寫第一版的時候,還是一名 “參賽選手”。後來比賽失利便和朋友一起做 IDC 創業。第二次改的時候,是我發現閱讀量在倆三個月內直接自己站點 top 到第一,加上參與了開源社群,維護了 LCTT-CLI 專案。最後第三次也就是這次,是因為通過了 RHCE 模擬考加上一年多積累。所以這次的內容或是排版都應是最棒!BTW:這篇文章在我的部落格IT兄弟盟,依舊是第一的閱讀量!
一開始寫這篇文章是因為兼職創業 IDC 公司運維,需要一點 shell script 來實現某些需求。雖然現在已經是 Python 的時代了。插個話題,我怎麼理解 Python 和 Shell 呢?拿游泳來做個比喻:前者是正規游泳館,有正規教練輔助相伴;後者是鄉下小湖泊,麻雀雖小五臟俱全。人工智慧選中的 Python 勢必鋒不可當,經典的 Shell 也相當精妙絕倫。比如以前我寫 Shell 的時候用了很多 if else
語句、 case
語句,有 test
語句,懂得 ||
&&
;
輔助,這是最小白的。後面學習了很多比較運算子,但多數還是在積累命令數量以及條件語句。再到現在,我開始去思考命令和命令之間存在的關係、語句分隔符的意義、BASH 控制結構等等。
所以今天和大家分享的主要是 “命令替換” 以及 “引數擴充套件” 。
什麼是命令替換
簡單的來說就是在 SHELL 內巢狀多條命令,一次性執行得到結果。
1、一層 SHELL 巢狀
# echo `whoami`
# echo $(whoami)
# echo "hello,`whoami`"
# echo "hello,$(whoami)"
2、二層 SHELL 巢狀
# echo `cat ./gn2.txt` | sed -s "s;$; --list;"
使用 ``
讀取檔案內容,再使用管道符二次處理後。執行!
注意:這裡已經用了一層巢狀,以下多個小節會套用以實現二層巢狀。
a. 使用 "$()" 進行二層巢狀
b. 使用 "|" 進行命令導向
c. 注意事項以及解答一些疑問
可能有讀者已經注意到了,之前在簡單 SHELL 一層巢狀中說了巢狀還有另一種。那為什麼不使用 ` `
進行巢狀。
- 根本的原因是:
` `
不支援命令巢狀執行!- 強制執行。也只能認出第一組,其餘按照空格作為間隔各個執行 或 按照管道符(含)直到末尾執行。
- 比較陳舊。容易與“單引號”混淆。
- 它是美式鍵盤左上角 ESC 下面的包含
~
的反引號鍵!
- 它是美式鍵盤左上角 ESC 下面的包含
- 已有替代品。
$(...)
格式受到POSIX標準支援,也利於巢狀。$()
可以多層巢狀類似$($($()))
,但如果內部有一個` `
也是可以執行的喲(出於相容考慮)!
3、進階
之前我們介紹了
``
和$(...)
,這倆種命令執行。想來現在你一定對命令執行有比較深的理解了。現在,我們需要再進階一下~
1、 (cmd)
與 {var}
關於 ( )
與 { }
,和 命令替換
一樣都是 shell 擴充套件
父類下的相關概念。
提示:{}
頭部大括號右側必須有一個空格,尾部括號左側必須有分號結尾。
# ( echo firest;echo second; )
# { echo third;echo fourth; }
注意: ( )
只是對一串命令重新開一個 子 shell 進行執行, { }
對一串命令在 當前 shell 執行。
2、()
與 {}
造成的影響
a. ()
括號內的語句影響在括號內
# var=source
# ( echo $var;var=global;echo $var; )
# echo $var
b. {}
括號內的語句影響到全域性。
# echo $var
# { echo $var;var=global;echo $var; }
# echo $var
注意:{}
改變 var
的變數以後,外部也受到了影響。
什麼是引數擴充套件
引數擴充套件的基本格式是 ${ parameter }
,擴充套件的結果是 ${ parameter }
被替換為相應的值。
1、例項一
echo $1 $11
echo $1 ${11}
首先解釋下 ${1..9}
是什麼意思。在我們寫 Shell
時必不可免的需要傳遞引數以實現自定義變數。當超過阿拉伯數字 9
以後。就需要使用 ${ parameter }
明確告訴Shell
第 11
個引數是 ${11}
。
提示:上圖顯示 101
就是因為 $11
不滿足 [1-9]{1}
。系統將 11
拆分成 $1
和 1
,所以運算後結果是 101
。
2、例項二
ban=ban
echo a $banana
echo a ${ban}ana
這個例項中,我想輸出 banana
。已經定義了一個 ban
的變數為 ban
,只要加上 ana
就可以成為 “笨啦啦”。
但是很顯然的不加 {}
是無法做到使變數 $ban
配合 ana
顯示出 banana
的!
什麼是變數擴充套件
從官方定義上來說,我並不應該將 “變數擴充套件” 無中生有出來。
"
$
字元引入引數擴充套件,命令替換或算術擴充套件。" —— 官方手冊
主要是出於倆個方面考慮:
- 多數接受。國內出現了大量 ”變數擴充套件“ 的文章,多數人已經接受這個名稱。
- 便於理解。引數就是
${...}
括號內的東西,而變數一詞可表示所有操作圍繞變數展開。 - 便於記錄。切分以後,對寫這篇文章的排版有幫助。亦可以從基礎、中級、高階有一定水平劃分。
例項:
var='This is one test sentence.'
var1=parameter
var2=word
現在我們有了這樣的一個句子,我希望做一些判斷、摘取(或者說:切片)或修改。我該如何操作?
1、變數替換
a. ${parameter:-word}
# echo ${var1:-$var2}
parameter
# var1=
# echo ${var1:-$var2}
word
如果 var1
未設定或為空,則替換成 var2
。
b. ${parameter:=word}
同上。位置引數和特殊引數不能以這種方式分配。
c. ${parameter:?word}
# var1=
# echo ${var1:?var2}
bash: var1: var2
# echo $?
1
當變數 var1
未設定或為空,shell 也是可互動時,進行報錯並且退出。如果 shell 不可互動,則發生變數替換。
d. ${parameter:+word}
# echo $var1
parameter
# echo $var2
word
# echo ${var1:+$var2}
word
# echo $var1
parameter
如果 var1
為空或未設定,那麼就什麼都不做。不然使用 var2
進行替換。
提示: 在我測試的時候,我發現並不是全域性生效的。
2、變數切片
a. 範圍切片(同方向)
# echo ${var:8:17}
one test sentence
注意:倆個數字都是從頭開始數的。
b. 範圍切片(非同向)
# echo ${var:8:-1}
one test sentence
# echo ${var:8:(-1)}
one test sentence
提示:倆種寫法都是正確的。
c. 切片位置
# a='This is one'
# echo ${#a}
11
提示 :首先建立變數 a='This is one'
,然後使用 echo ${#a}
將字元數量讀了出來。
3、變數修改
a. 簡單修改
# echo ${var}
This is one test sentence.
# echo ${var/one/a}
This is a test sentence.
提示:個人認為這種是最好的方式了,可以範圍式修改(包含刪除)。
b. 簡單刪除
# echo ${var%sentence.}
This is one test
# echo ${var#This is}
one test sentence.
c. 附:表格
變數設定方式 | 說明 |
---|---|
${變數#關鍵字} | 若變數內容從頭開始的資料符合“關鍵字”,則將符合的最短資料刪除 |
${變數##關鍵字} | 若變數內容從頭開始的資料符合“關鍵字”,則將符合的最長資料刪除 |
${變數%關鍵字} | 若變數內容從尾開始的資料符合“關鍵字”,則將符合的最短資料刪除 |
${變數%%關鍵字} | 若變數內容從尾開始的資料符合“關鍵字”,則將符合的最長資料刪除 |
${變數/舊字串/新字串} | 若變數內容符合“舊字串”,則首個舊字元會被新字元替換。 |
${變數/舊字串//新字串} | 若變數內容符合“舊字串”,則全部舊字元會被新字元替換。 |
更深入學習,探索資料
- Bash 例項,第二部分
- Bash 參考手冊:Bash Reference Manual
- Shell-Expansions 章節:Shell-Expansions
- Shell Parameter Expansion 章節 Shell Parameter Expansion
相關文章
- shell中擴充套件命令套件
- vi 替換命令引數
- bash 引數替換中的模式匹配模式
- GNOME Shell Extension常用擴充套件套件
- 用javascript替換URL中的引數值JavaScript
- shell擴充套件——免互動指令碼套件指令碼
- C#學習筆記-方法引數、擴充套件方法C#筆記套件
- SPI擴充套件點在業務中的使用及原理分析套件
- 擴充套件叢集blk數套件
- 數論分塊擴充套件套件
- kotlin 擴充套件(擴充套件函式和擴充套件屬性)Kotlin套件函式
- sql中的擴充套件學習SQL套件
- Linux Shell程式設計(24)——命令替換Linux程式設計
- iOS 推送通知及推送擴充套件iOS套件
- JavaScript 原生物件及擴充套件JavaScript物件套件
- 安裝PHP及Memcache擴充套件PHP套件
- STL中的棧的擴充套件 (轉)套件
- Shell轉義字元與變數替換字元變數
- Hash分割槽表的使用及擴充套件套件
- exp匯出compress引數導致的imp時擴充套件太大套件
- 不容錯過這十款 GNOME Shell 擴充套件套件
- INFORMIX表的預設初始擴充套件、下一個擴充套件資料塊以及一個表允許的最大擴充套件數。ORM套件
- es6-數值擴充套件套件
- ES6數字擴充套件套件
- django實現自定義manage命令的擴充套件Django套件
- WCF擴充套件:行為擴充套件Behavior Extension套件
- CONNECT BY 擴充套件用法,實現獲取bom級聯擴充套件數量套件
- PHP擴充套件資料庫連線引數說明詳解PHP套件資料庫
- shell替換程式碼
- CentOS安裝RabbitMQ及PHP擴充套件CentOSMQPHP套件
- ?用Chrome擴充套件管理器, 管理你的擴充套件Chrome套件
- 將url中的指定引數替換的javascript程式碼例項JavaScript
- C#中的擴充套件類的理解C#套件
- 用Shell擴充套件實現原始碼統計程式套件原始碼
- 【Kotlin】擴充套件屬性、擴充套件函式Kotlin套件函式
- 使用命令擴充套件vmdk磁碟空間套件
- Sanic 擴充套件套件
- ORACLE 擴充套件Oracle套件