Shell:結構化語句

来源:https://www.cnblogs.com/Rohn/archive/2020/07/04/13234419.html
-Advertisement-
Play Games

ver: 1.0 博客:https://www.cnblogs.com/Rohn 本文介紹了Shell常用的結構化語句。 數組 數組(Array)是若幹數據的集合,其中的每一份數據都稱為元素(Element)。 Bash只支持一維數組(不支持多維數組),初始化時不需要定義數組大小,理論上可以存放無限 ...


目錄

數組

數組(Array)是若幹數據的集合,其中的每一份數據都稱為元素(Element)。

Bash只支持一維數組(不支持多維數組),初始化時不需要定義數組大小,理論上可以存放無限量的數據。

與大部分編程語言類似,數組元素的下標由0開始。

Shell數組用括弧來表示,元素用"空格"符號分割開。格式如下:

array_name=(ele1  ele2  ele3 ... elen)

Tips:賦值號=兩邊不能有空格,必須緊挨著數組名和數組元素。

獲取數組中的元素要使用下標[],下標可以是一個整數,也可以是一個結果為整數的表達式;當然,下標必須大於等於0。格式如下:

${array_name[index]}

Tips:array_name是數組名,index是下標。

Shell是弱類型的,它並不要求所有數組元素的類型必須相同,例如:

arr=(10 24 'ddd' 'ab22' 5)

獲取數組所有元素

使用@*可以獲取數組中的所有元素,格式如下:

${array_name[*]}
${array_name[@]}

獲取數組元素個數

使用#來獲取數組元素的個數,格式如下:

${#array_name[@]}
${#array_name[*]}

數組合併

數組合併,就是將兩個或兩個以上的數組合併成一個個數組,格式如下:

array_new=(${array1[@]}  ${array2[@]}...${arrayn[@]})
array_new=(${array1[*]}  ${array2[*]}...${arrayn[*]})

刪除數組元素

使用unset關鍵字來刪除數組元素,格式如下:

unset array_name[index]

如果不寫下標,則代表刪除整個數組所有元素,格式如下:

unset array_name

實例

測試ip是否ping通

#!/usr/bin/env bash
# Author: Rohn
# Version: 1.0
# Create Time: 2020/06/13
# Test network connectivity

arr_num=(3 11 25 32 200)
for i in ${arr_num[*]}; do
  ip=192.168.110.${i}
  ping -c 1 $ip >/dev/null 2>&1
  if [ $? -eq 0 ]; then
    echo "${ip} is ok."
  else
    echo "${ip} is unreachable."
  fi
done

選擇結構

Shell中的選擇結構(分支結構)有兩種形式,分別是 if-elsecase-in語句,它們都根據命令的退出狀態來判斷條件是否成立。

if-else語句

基本格式

基本結構格式:

if condition; then
  statement(s)
fi

condition是判斷條件,如果condition成立(返回True),那麼then後邊的語句將會被執行;如果 condition不成立(返回False),那麼不會執行任何語句。

Tips:最後必須以fi來閉合,fi就是if 倒過來拼寫。

if-else

如果有兩個分支,就可以使用if-else語句,格式:

if condition; then
  statement1
else
  statement2
fi

如果condition成立,那麼then後邊的 statement1語句將會被執行;否則,執行else 後邊的statement2語句。

if-elif-else

當分支比較多時,可以使用if-elif-else 結構,格式:

if condition1; then
  statement1
elif condition2;then
  statement2
...
else
  statementn
fi

Tips:ifelif後邊都得跟著then

語句的執行邏輯:

  • 如果condition1成立,那麼執行statement1,如果不成立,則執行elif語句;
  • 如果elif語句不成立,則執行else語句;

case-in語句

當分支較多,且判斷條件比較簡單時,推薦使用case-in語句。格式如下:

case expression in
  pattern1)
    statement1
    ;;
  pattern2)
    statement2
    ;;
  ...
  *)
    statementn
esac
  • expression表示表達式,既可以是一個變數、一個數字、一個字元串,還可以是一個數學計算表達式,或者是命令的執行結果,只要能夠得到expression的值就可以。
  • pattern表示匹配模式,可以是一個數字、一個字元串,甚至是一個簡單的正則表達式。

case會將expression的值與 pattern1pattern2...patternn逐個進行匹配:

  • 如果expression和某個模式(比如 pattern2)匹配成功,就會執行這模式(比如 pattern2)後面對應的所有語句(該語句可以有一條,也可以有多條),直到遇見雙分號;;才停止;然後整個case-in語句就執行完了,程式會跳出整個 case-in語句,執行esac後面的其它語句。
  • 如果 expression 沒有匹配到任何一個模式,那麼就執行*)後面的語句(*表示其它所有值),直到遇見雙分號;;或者esac才結束。*)相當於多個if分支語句中最後的else部分。

Tips:分支*)並不是什麼語法規定,它只是一個正則表達式,*表示任意字元串,所以不管expression的值是什麼,*)總能匹配成功。因此,可以沒有*)部分,如果expression沒有匹配到任何一個模式,那麼就不執行任何操作。

除最後一個分支外(這個分支可以是普通分支,也可以是*)分支),其它的每個分支都必須以;;結尾,;;代表一個分支的結束,不寫的話會有語法錯誤。最後一個分支可以寫;;,也可以不寫,因為無論如何,執行到esac都會結束整個case-in語句。

case-inpattern部分支持簡單的正則表達式,具體來說,可以使用以下幾種格式:

格式 說明
* 表示任意字元串。
[abc] 表示 a、b、c 三個字元中的任意一個。比如,[15ZH] 表示 1、5、Z、H 四個字元中的任意一個。
[m-n] 表示從 m 到 n 的任意一個字元。比如,[0-9] 表示任意一個數字,[0-9a-zA-Z] 表示字母或數字。
| 表示多重選擇,類似邏輯運算中的或運算。比如,abc | xyz 表示匹配字元串 "abc" 或者 "xyz"。

;;&終止每個條件塊,例如:

read -n 1 -p "Type a character > "
echo
case $REPLY in
  [[:upper:]])    echo "'$REPLY' is upper case." ;;&
  [[:lower:]])    echo "'$REPLY' is lower case." ;;&
  [[:alpha:]])    echo "'$REPLY' is alphabetic." ;;&
  [[:digit:]])    echo "'$REPLY' is a digit." ;;&
  [[:graph:]])    echo "'$REPLY' is a visible character." ;;&
  [[:punct:]])    echo "'$REPLY' is a punctuation symbol." ;;&
  [[:space:]])    echo "'$REPLY' is a whitespace character." ;;&
  [[:xdigit:]])   echo "'$REPLY' is a hexadecimal digit." ;;&
esac

輸出結果如下:

Type a character > a
'a' is lower case.
'a' is alphabetic.
'a' is a visible character.
'a' is a hexadecimal digit.

迴圈結構

迴圈結構語句大致分為4種:

  • while
  • until
  • for
  • select

while語句

當條件滿足時,while重覆地執行一組語句,當條件不滿足時,就退出while迴圈。格式如下:

while condition; do
  statements
done

執行流程如下:

  • 先對condition進行判斷,如果該條件成立,就進入迴圈,執while迴圈體中的語句,也就是dodone之間的語句。這樣就完成了一次迴圈。
  • 每一次執行到done的時候都會重新判斷condition是否成立,如果成立,就進入下一次迴圈,繼續執行dodone之間的語句,如果不成立,就結束整個while迴圈,執行done後面的其它Shell代碼。
  • 如果一開始condition就不成立,那麼程式就不會進入迴圈體。

死迴圈

格式一:

while true; do
  statements
done

格式二:

while [ 1 ]; do
  statements
done

until語句

until迴圈當判斷條件不成立時才進行迴圈,一旦判斷條件成立,就終止迴圈。

until condition; do
  statements
done

until迴圈的執行流程為:

  • 先對condition進行判斷,如果該條件不成立,就進入迴圈,執行until迴圈體中的語句(dodone之間的語句),這樣就完成了一次迴圈。
  • 每一次執行到done的時候都會重新判斷condition是否成立,如果不成立,就進入下一次迴圈,繼續執行迴圈體中的語句,如果成立,就結束整個 until迴圈,執行done後面的其它Shell代碼。

for語句

C語言風格的 for 迴圈

格式如下:

for((exp1; exp2; exp3)); do
  statements
done

exp1exp2exp3是三個表達式,其中exp2是判斷條件,for迴圈根據exp2的結果來決定是否繼續下一次迴圈;

它的運行過程為:

  1. 先執行exp1
  2. 再執行exp2,如果它的判斷結果是成立的,則執行迴圈體中的語句,否則結束整個for迴圈。
  3. 執行完迴圈體後再執行exp3
  4. 重覆執行2、3步驟,直到exp2的判斷結果不成立,就結束迴圈。

for-in迴圈

格式如下:

for variable in value_list; do
  statements
done

variable表示變數,value_list表示取值列表。

每次迴圈都會從value_list中取出一個值賦給變數 variable,然後進入迴圈體(dodone之間的部分),執行迴圈體中的statements。直到取完value_list中的所有值,迴圈就結束了。

value_list

  • 具體的值,例如:
for i in 1 2 3 'dd';do echo $i;done
  • {start..end},例如:
# 求1到10的和
sum=0
for i in {1..10}; do
  sum=$((sum+i))
done
echo $sum
  • 命令的執行結果,例如:
# 求100以內偶數的和
for i in $(seq 2 2 100); do
  sum=$((sum+i))
done
echo $sum
  • 通配符,例如:
# 列印當前路徑.log結尾的文件
for i in *.log; do echo $i;done

Tips:若當前路徑無.log結尾的文件,則會列印*.log

  • 特殊變數,$*$@等,例如:
for i in $@; do
  sum=$((sum+i))
done
echo $sum

select-in語句

select-in迴圈用來增強交互性,它可以顯示出帶編號的菜單,用戶輸入不同的編號就可以選擇不同的菜單,並執行不同的功能,非常適合終端(Terminal)這樣的交互場景。格式如下:

select variable in value_list; do
  statements
done

variable表示變數,value_list表示取值列表。

例如:

echo "選擇你要學習的科目:"
select i in 'Linux' 'Python' 'Java' 'C++' 'PHP'; do
  echo "你選擇了${i}。"
done

結果如下:

選擇你要學習的科目:
1) Linux
2) Python
3) Java
4) C++
5) PHP
#? 5
你選擇了PHP。
#? 2
你選擇了Python。
#? 666
你選擇了。

Tips:select是死迴圈,輸入空值或者輸入的值無效,都不會結束迴圈,只有遇到break語句,或者按下Ctrl+D組合鍵才能結束迴圈。

例如:

echo "選擇你要學習的科目:"
select i in 'Linux' 'Python' 'Java' 'C++' 'PHP'; do
  echo "你選擇了${i}。"
  break
done

結果如下:

選擇你要學習的科目:
1) Linux
2) Python
3) Java
4) C++
5) PHP
#? 5
你選擇了PHP。

select-in語句常和case-in語句一起使用。

break

格式如下:

break n

n表示跳出迴圈的層數,如果省略n,則表示跳出當前。

continue

格式如下:

continue n

n表示迴圈的層數:

  • 如果省略n,則表示continue只對當前層次的迴圈語句有效,遇到continue會跳過本次迴圈,忽略本次迴圈的剩餘代碼,直接進入下一次迴圈。
  • 如果帶上n,比如n的值為2,那麼continue 對內層和外層迴圈語句都有效,不但內層會跳過本次迴圈,外層也會跳過本次迴圈,其效果相當於內層迴圈和外層迴圈同時執行了不帶ncontinue

break的區別:

  • break用來結束當前整個迴圈;
  • continue用來結束本次迴圈,直接跳到下一次迴圈,如果迴圈條件成立,還會繼續迴圈;

函數

函數的本質是一段可以重覆使用的腳本代碼,這段代碼被提前編寫好了,放在了指定的位置,使用時直接調取即可。

函數定義

格式如下:

function func_name() {
    statements
    [return value]
}

Tips:關鍵詞function是可選的,但必須在一個項目中保持一致。

說明:

  • function是Shell中的關鍵字,專門用來定義函數,可以不寫,但要求在整個項目腳本中保持一致,即統一不寫或都寫;
  • func_name是函數名,按照約定規範,函數名後面必須帶上()
  • statements是函數要執行的代碼,也就是一組語句;
  • return value表示函數的返回值,其中return 是Shell關鍵字,專門用在函數中返回一個值;這一部分可以寫也可以不寫。

函數調用

調用Shell函數時可以給它傳遞參數,也可以不傳遞。如果不傳遞參數,直接給出函數名字即可,格式如下:

func_name

如果傳遞參數,那麼多個參數之間以空格分隔:

func_name param1 param2 param3...

Tips:不管是哪種調用方式,函數名字後面都不需要帶()

函數參數

函數參數是Shell位置參數的一種,在函數內部可以使用$n來接收,例如,$1表示第一個參數,$2表示第二個參數,依次類推。

除了$n,還有另外三個比較重要的變數:

  • $#可以獲取傳遞的參數的個數;
  • $@或者$*可以一次性獲取所有的參數

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 使用博客園寫博客也有2年有餘了,對博客園是有一種莫名的親切感和深刻的感情的,這2多年來一直堅持寫著博客,也是對自己的一個很好的技術歷程總結。每次學習了一些新的技術,或者有一些感興趣的方向,都會通過隨筆進行記錄,有時候也會總結很多自己的開發成果,隨著技術路線的成熟,基本上是分享我的.NET相關技術。 ...
  • vs2019創建webapi 1.創建新的項目 2.選擇.NET CORE的ASP .NET CORE WEB應用程式 3.定義項目名稱和存放地點 4.選擇API創建項目 5.刪除原本的無用的類 6.添加新的方法類 7.設置路由 using Microsoft.AspNetCore.Componen ...
  • 前言 IdentityServer4 是為ASP.NET Core系列量身打造的一款基於 OpenID Connect 和 OAuth 2.0 認證的框架 IdentityServer4官方文檔:https://identityserver4.readthedocs.io/ 看這篇文章前預設你對Id ...
  • 在i.MXRT所有Flash下載演算法里,痞子衡認為Segger J-Link版的Flash下載演算法是最應該掌握的,畢竟Segger提供了完善的軟體工具支持(Jlink commander、J-Flash、Ozone),既可獨立使用,也可嵌入其他MCU開發環境中使用(實際上它與Keil演算法文件是相容的... ...
  • 最近發現了一個好玩,有趣的終端連接工具mobaxterm。Linux下有很多終端工具例如CRT,Xshell,但小伙伴就有疑問問什麼要用mobaxterm, 主要是mobaxterm是開源的免費的(其他都是收費的)。 廢話不多說我們立即進入正題。 下載與安裝。 0.打開你的瀏覽器:用CV大法進入官網 ...
  • 冒泡排序: 演算法重覆走訪要排序的數列,一次比較兩個元素,如果它們順序錯誤就交換它們的位置,這樣最大的數就到了最後,重覆操作即可得到有序數列。 冒泡排序演算法運行: 1. 比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。 2. 對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對。在這一點, ...
  • 以下內容,來自網路資料整理和個人安裝使用結果。後續會持續更新 ...
  • 由於一些原因,我重新安裝了系統並把之前的鏡像與虛擬機刪除了,現在又全新安裝一次CenOS6.7,順便查缺補漏,帶領各位讀者一起安裝。 (本文適合小白/新人,大佬們請忽略),帶有可選步驟的可以忽略,1-20是VMware軟體的設置,系統的安裝從21-45條開始,剩餘部分是後續配置建議。如發現問題或有疑 ...
一周排行
    -Advertisement-
    Play Games
  • 基於.NET Framework 4.8 開發的深度學習模型部署測試平臺,提供了YOLO框架的主流系列模型,包括YOLOv8~v9,以及其系列下的Det、Seg、Pose、Obb、Cls等應用場景,同時支持圖像與視頻檢測。模型部署引擎使用的是OpenVINO™、TensorRT、ONNX runti... ...
  • 十年沉澱,重啟開發之路 十年前,我沉浸在開發的海洋中,每日與代碼為伍,與演算法共舞。那時的我,滿懷激情,對技術的追求近乎狂熱。然而,隨著歲月的流逝,生活的忙碌逐漸占據了我的大部分時間,讓我無暇顧及技術的沉澱與積累。 十年間,我經歷了職業生涯的起伏和變遷。從初出茅廬的菜鳥到逐漸嶄露頭角的開發者,我見證了 ...
  • C# 是一種簡單、現代、面向對象和類型安全的編程語言。.NET 是由 Microsoft 創建的開發平臺,平臺包含了語言規範、工具、運行,支持開發各種應用,如Web、移動、桌面等。.NET框架有多個實現,如.NET Framework、.NET Core(及後續的.NET 5+版本),以及社區版本M... ...
  • 前言 本文介紹瞭如何使用三菱提供的MX Component插件實現對三菱PLC軟元件數據的讀寫,記錄了使用電腦模擬,模擬PLC,直至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1. PLC開發編程環境GX Works2,GX Works2下載鏈接 https:// ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • 1、jQuery介紹 jQuery是什麼 jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype之後又一個優秀的JavaScript代碼庫(或JavaScript框架)。jQuery設計的宗旨是“write Less,Do More”,即倡導寫更少的代碼,做更多的事情。它封裝 ...
  • 前言 之前的文章把js引擎(aardio封裝庫) 微軟開源的js引擎(ChakraCore))寫好了,這篇文章整點js代碼來測一下bug。測試網站:https://fanyi.youdao.com/index.html#/ 逆向思路 逆向思路可以看有道翻譯js逆向(MD5加密,AES加密)附完整源碼 ...
  • 引言 現代的操作系統(Windows,Linux,Mac OS)等都可以同時打開多個軟體(任務),這些軟體在我們的感知上是同時運行的,例如我們可以一邊瀏覽網頁,一邊聽音樂。而CPU執行代碼同一時間只能執行一條,但即使我們的電腦是單核CPU也可以同時運行多個任務,如下圖所示,這是因為我們的 CPU 的 ...
  • 掌握使用Python進行文本英文統計的基本方法,並瞭解如何進一步優化和擴展這些方法,以應對更複雜的文本分析任務。 ...
  • 背景 Redis多數據源常見的場景: 分區數據處理:當數據量增長時,單個Redis實例可能無法處理所有的數據。通過使用多個Redis數據源,可以將數據分區存儲在不同的實例中,使得數據處理更加高效。 多租戶應用程式:對於多租戶應用程式,每個租戶可以擁有自己的Redis數據源,以確保數據隔離和安全性。 ...