Linux 下Shell 腳本幾種基本命令替換區別


前言:

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

一開始寫這篇文章是因為兼職創業 IDC 公司運維,需要一點 shell script 來實現某些需求。雖然現在已經是 Python 的時代了。插個話題,我怎么理解 PythonShell 呢?拿游泳來做個比喻:前者是正規游泳館,有正規教練輔助相伴;后者是鄉下小湖泊,麻雀雖小五臟俱全。人工智能選中的 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 下面的包含 ”~“ 的反引號鍵!
  • 已有替代品。$(...) 格式受到POSIX標准支持,也利於嵌套。
    • $() 可以多層嵌套類似 $($($())) ,但如果內部有一個 `` 也是可以執行的喲(出於兼容考慮)!

三、進階

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

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

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 } 明確告訴Shell11 個參數是 ${11}

提示:上圖顯示 101 就是因為 $11 不滿足 [1-9]{1} 。系統將 11 拆分成 $11 ,所以運算后結果是 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM